What does the registerNatives() method do?

45,386

Solution 1

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

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.

  1. 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 function RegisterNatives.

    c. Make sure that in your Java code, your Java registerNatives method is called prior to any calls to other native methods.

OR

  1. 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 function RegisterNatives.

    b. The Java VM will automatically look for and call JNI_OnLoad when your native library is loaded by System.loadLibrary, which you should already be calling, probably in a static initializer for your class. (You get the required env pointer by calling the GetEnv function in the table that the vm pointer points to.)

Share:
45,386

Related videos on Youtube

Hubris
Author by

Hubris

I'm a Software Engineer mainly in the C#/.NET world, with a love of travel, cooking and dancing.

Updated on July 05, 2022

Comments

  • Hubris
    Hubris almost 2 years

    In java, what does the private static method registerNatives() of the Object class do?

  • Pavel P
    Pavel P over 11 years
    You wrote fully decorated JNI function name, which makes it confusing: is Java_java_lang_Object_registerNatives called by VM automatically, or c/c++ code has to call that function and there is no need for all that java gobblygook
  • C. K. Young
    C. K. Young over 11 years
    @Pavel By default, a native method methodName in class fully.qualified.ClassName is searched under the C name Java_fully_qualified_ClassName_methodName (which your C-side code must export). You can call JNIEnv's RegisterNatives method to override this linkage. In other words, if you don't use RegisterNatives first, "all that java gobblygook" [sic] is required.
  • Pavel P
    Pavel P over 11 years
    Ah, ok, so by exporting only 1 function Java_java_lang_Object_registerNatives I can actually link all my JNI stuff by checking value of cls. I missed the part that registerNatives is actually part of java itself. So... when some class is about to be used, what's the order of actions that JVM uses to link natives? It seems that if natives's aren't registered yet (from c/c++), then JVM checks for all these exported names, if they aren't present then it tries to use Object.registerNatives (or the other way around?). By the way, the jni book link is dead.
  • C. K. Young
    C. K. Young over 11 years
    If you haven't called RegisterNatives, and the exported names aren't available, then you will get a runtime error when you try to call the method. Object.registerNatives is an internal method of OpenJDK's implementation of java.lang.Object, called from its class initialiser, and its sole purpose is to register the native methods that pertain to java.lang.Object only. If you are writing your own native library, it's up to you to register your library's native methods yourself (should you wish to).
  • choxsword
    choxsword over 2 years
    best answer I've ever seen