What does the registerNatives() method do?
JavaCObjectMethodsJava Native-InterfaceJava Problem Overview
In java, what does the private static method registerNatives()
of the Object class do?
Java Solutions
Solution 1 - Java
The other answers are technically correct, but not very useful for someone with no JNI experience. :-)
Normally, in order for the JVM to find your native functions, they have to be named a certain way. e.g., for java.lang.Object.registerNatives
, the corresponding C function is named Java_java_lang_Object_registerNatives
. By using registerNatives
(or rather, the JNI function RegisterNatives
), you can name your C functions whatever you want.
Here's the associated C code (from OpenJDK 6):
static JNINativeMethod methods[] = {
{"hashCode", "()I", (void *)&JVM_IHashCode},
{"wait", "(J)V", (void *)&JVM_MonitorWait},
{"notify", "()V", (void *)&JVM_MonitorNotify},
{"notifyAll", "()V", (void *)&JVM_MonitorNotifyAll},
{"clone", "()Ljava/lang/Object;", (void *)&JVM_Clone},
};
JNIEXPORT void JNICALL
Java_java_lang_Object_registerNatives(JNIEnv *env, jclass cls)
{
(*env)->RegisterNatives(env, cls,
methods, sizeof(methods)/sizeof(methods[0]));
}
(Notice that Object.getClass
is not in the list; it will still be called by the "standard" name of Java_java_lang_Object_getClass
.) For the functions listed, the associated C functions are as listed in that table, which is handier than writing a bunch of forwarding functions.
Registering native functions is also useful if you are embedding Java in your C program and want to link to functions within the application itself (as opposed to within a shared library), or the functions being used aren't otherwise "exported", since these would not normally be found by the standard method lookup mechanism. Registering native functions can also be used to "rebind" a native method to another C function (useful if your program supports dynamically loading and unloading modules, for example).
I encourage everybody to read the JNI book, which talks about this and much more. :-)
Solution 2 - Java
What might be slightly confusing is that the code shown for java.lang.Object.registerNatives
in a previous answer is just an example of how to register native functions. This is the code that (in the implementation of OpenJDK) registers native functions for class Object. To register native functions for your own class, you must call the JNI function RegisterNatives
from the native code in your own library. This might sound a bit circular, but there are a couple ways to break the loop.
-
Follow the example of this implementation of class Object:
a. In your Java class, declare a native method (preferably static) named
registerNatives
(or any other name. it doesn't matter).b. In your native code, define a function named
Java_<your fully qualified class name>_registerNatives
, which contains a call to the JNI functionRegisterNatives
.c. Make sure that in your Java code, your Java
registerNatives
method is called prior to any calls to other native methods.
OR
-
Use
JNI_OnLoad
a. In your native library define a function
jint JNI_OnLoad(JavaVM *vm, void *reserved)
. In the body of this function, call the JNI functionRegisterNatives
.b. The Java VM will automatically look for and call
JNI_OnLoad
when your native library is loaded bySystem.loadLibrary
, which you should already be calling, probably in a static initializer for your class. (You get the requiredenv
pointer by calling theGetEnv
function in the table that thevm
pointer points to.)
Solution 3 - Java
It is used on such scene :
C or C++ work as host, and Java the JVM as client. (C load jvm.dll
and use JNI_CreateJavaVM
to create a JVM)
When java code need to call host's C function,
If you still use jni dll (System.loadLibrary("foo.dll");
) to bind the native java method, the memory space of dll is not the same as C host. (It still works if the function you called is host state irrelevant, but you cannot access host's state values in this way)
Here you need to use env->RegisterNatives()
at host to inject(bind,expose,export) host's C functions to the JVM.