-
Notifications
You must be signed in to change notification settings - Fork 56
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Java.Interop] Java
native
method registration
The Java Native Interface Functions [0] mostly covers calling Java code *from* non-Java code, e.g. JNIEnv::CallVoidMethod() can be used to call all Java instance methods which have a `void` return type. What about the calling non-Java code from Java? That can't be *fully* done through the JNIEnv type; it also requires cooperation with Java bytecode, though the use of `native` method declarations [1]: // Java class Example { public native void m (); } Before Java code can invoke the Example.m() instance method, that method must first be *registered* via JNIEnv::RegisterNatives() [2]. What we have, then, is a two step process: 1. Write/generate/otherwise obtain Java bytecode with `native` method declarations. 2. At runtime, "somehow" ensure that the native methods declared in (1) are *registered* before they are first used from Java. To date, JNIEnv::RegisterNatives() has been used in numerous places in Java.Interop via JniType.RegisterNativeMethods() -- e.g. the JavaProxyObject static constructor -- but the current architecture doesn't support (2), as there is no way to *ensure* that e.g. JavaProxyObject registers its native methods before Java invokes them. (Normal use would preclude that, but if someone uses Reflection to create a JavaProxyObject instance...) How do we ensure that "something" -- native method registration -- happens before anything important is done with the Java type? By using Java static initalizers, and introducing the new com.xamarin.java_interop.ManagedPeer.registerNativeMembers() method: class Example { static final String assemblyQualifiedName = "Example, ..."; static { com.xamarin.java_interop.ManagedPeer.registerNativeMembers ( Example.class, assemblyQualifiedName, "method-blob" ); } } ManagedPeer.registerNativeMembers() will call into managed code and (eventually) call JNIEnv::RegisterNatives() for the Java type. Next important question: How does ManagedPeer.registerNativeMembers() *actually* register the native methods? Additionally, this mechanism needs to help support the future desired Ahead-Of-Time (AOT) compilation mechanism of jnimarshalmethod-gen (176240d). The answer is the new JniRuntime.JniTypeManager.RegisterNativeMembers() virtual method. The default implementation will do the following: 1. Lookup the assembly to use. 1.a: Check to see if there is a corresponding -JniMarshalMethods assembly, as generated by jnimarshalmethod-gen. For example, if the type to register is in Example.dll, then the assembly Example-JniMarshalMethods.dll will be loaded. 1.b: If (1.a) fails, then use the assembly that contains the Type being registered -- the assemblyQualifiedName parameter provided to ManagedPeer.registerNativeMembers(). 2. Lookup the type to use, which is the type's FullName resolved from the assembly found in (1). 3. Look for the __RegisterNativeMembers() method on the type from (2) and invoke it, passing the JniType which corresponds to the Java class to register, and the "method-blob" value. For example, when registering methods for the Example type in Example.dll, the following methods will be searched for, and the first method found will be invoked: Example.__RegisterNativeMembers() from Example-JniMarshalMethods.dll Example.__RegisterNativeMembers() from Example.dll If no such __RegisterNativeMembers() method is found, we bail. JniRuntime.JniTypeManager subclasses may do something else. For example, Xamairn.Android could (will?) process the "method-blob" string as it normally does within JNIEnv.RegisterJniNatives(). The benefit of this architecture is that it allows "normal user" assemblies to be post-processed to emit the -JniMarshalMethods assembly, and use *that* for method registration at runtime. This in turn avoids the need to emit marshaling code at runtime, as marshaling code was previously emitted. [0]: http://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/functions.html [1]: http://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/design.html#compiling_loading_and_linking_native_methods [2]: http://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/functions.html#RegisterNatives
- Loading branch information
Showing
17 changed files
with
224 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.