You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Allowing JVM-hosted code to invoke managed code requires the use of Java Callable Wrappers for all Java.Lang.Object subclasses. The Java Callable Wrapper contains Java native method declarations for all methods implemented in managed code, e.g. by overriding a virtual method, implementing an interface method, or placing [Java.Interop.ExportAttribute] on a method.
Java Callable Wrappers are currently implemented by using Java source code as an intermediary: JavaCallableWrapperGenerator generates Java source code, which is later compiled by javac to produce Java byte code for later inclusion into an Android application.
We have historically pondered updating Xamarin.Android.Tools.Bytecode to be a read/write API instead of a read-only API, largely for performance reasons: we could avoid the overhead of writing .java files and invoking javac if we just directly emitted a .jar file containing relevant .class files.
We now have another reason to ponder this idea: Full Kotlin support. Kotlin "name mangles" method names in various contexts, emitting Java byte code method names which are not valid Java identifiers:
Note the example.AbstractUnsigned.m-WZ4Q5Ns() method: it cannot be overridden from Java:
// error: JavaSubclassAbstractUnsigned is not abstract and does not override abstract method m-WZ4Q5Ns(int) in AbstractUnsignedclassJavaSubclassAbstractUnsignedextendsexample.AbstractUnsigned {
}
So long as we use Java source code as an intermediary, we cannot override or implement Kotlin name-mangled methods.
We could use Kotlin as an intermediate language ("Kotlin Callable Wrappers," anyone?)...
...but why add Kotlin as an intermediate language when we could instead just write Java byte code directly. This would allow the Java Callable Wrapper process to be faster -- no javac invocation would be required -- and means that we avoid any "pesky" issues caused by Kotlin name mangling.
The text was updated successfully, but these errors were encountered:
…537)
Context: #534
Context: #535
Context: 0065de4
There are cases where Kotlin generates Java methods that are not
valid Java identifiers:
// `javap` output for a Kotlin type using UInt parameters
public abstract class Bar {
abstract void foo-WZ4Q5Ns(int);
}
public interface IBar {
void foo-WZ4Q5Ns(int);
}
In this case we cannot allow the user to inherit from the class or
implement the interface as the mangled method cannot be present
within Java Callable Wrapper source code.
We still need the class to be bound because there might be a Kotlin-
created subclass that needs the base class to exist.
There's no foolproof way to mark these as "not implementable". The
best we can do for now is to detect if the user implements them in
the `<GenerateJavaStubs/>` task / `JavaCallableWrapperGenerator` and
give an informative error at that point.
Update `JavaCallableWrapperGenerator` so that when a Kotlin-generated
mangled method name is encountered, an XA4213 error is emitted:
error XA4213: Cannot override Kotlin-generated method 'foo-WZ4Q5Ns'
because it is not a valid Java method name.
This method can only be overridden from Kotlin.
…537)
Context: #534
Context: #535
Context: 0065de4
There are cases where Kotlin generates Java methods that are not
valid Java identifiers:
// `javap` output for a Kotlin type using UInt parameters
public abstract class Bar {
abstract void foo-WZ4Q5Ns(int);
}
public interface IBar {
void foo-WZ4Q5Ns(int);
}
In this case we cannot allow the user to inherit from the class or
implement the interface as the mangled method cannot be present
within Java Callable Wrapper source code.
We still need the class to be bound because there might be a Kotlin-
created subclass that needs the base class to exist.
There's no foolproof way to mark these as "not implementable". The
best we can do for now is to detect if the user implements them in
the `<GenerateJavaStubs/>` task / `JavaCallableWrapperGenerator` and
give an informative error at that point.
Update `JavaCallableWrapperGenerator` so that when a Kotlin-generated
mangled method name is encountered, an XA4213 error is emitted:
error XA4213: Cannot override Kotlin-generated method 'foo-WZ4Q5Ns'
because it is not a valid Java method name.
This method can only be overridden from Kotlin.
Context: Issue #524
Context: Issue #534
Allowing JVM-hosted code to invoke managed code requires the use of Java Callable Wrappers for all
Java.Lang.Object
subclasses. The Java Callable Wrapper contains Javanative
method declarations for all methods implemented in managed code, e.g. by overriding avirtual
method, implementing an interface method, or placing[Java.Interop.ExportAttribute]
on a method.Java Callable Wrappers are currently implemented by using Java source code as an intermediary:
JavaCallableWrapperGenerator
generates Java source code, which is later compiled byjavac
to produce Java byte code for later inclusion into an Android application.We have historically pondered updating
Xamarin.Android.Tools.Bytecode
to be a read/write API instead of a read-only API, largely for performance reasons: we could avoid the overhead of writing.java
files and invokingjavac
if we just directly emitted a.jar
file containing relevant.class
files.We now have another reason to ponder this idea: Full Kotlin support. Kotlin "name mangles" method names in various contexts, emitting Java byte code method names which are not valid Java identifiers:
Note the
example.AbstractUnsigned.m-WZ4Q5Ns()
method: it cannot be overridden from Java:So long as we use Java source code as an intermediary, we cannot override or implement Kotlin name-mangled methods.
We could use Kotlin as an intermediate language ("Kotlin Callable Wrappers," anyone?)...
...but why add Kotlin as an intermediate language when we could instead just write Java byte code directly. This would allow the Java Callable Wrapper process to be faster -- no
javac
invocation would be required -- and means that we avoid any "pesky" issues caused by Kotlin name mangling.The text was updated successfully, but these errors were encountered: