Search code examples
javajvmjava-native-interfacedynamic-library

How can jvm check arguments and return type when using jni invoking? How to implement this type checking?


JNI specification require the function must be placed in extern "C" block. But C linkage doesn't contain a type descriptor. So when you invoke a native method in java code, how can jvm check if the argument number/order/type and return type of the native code in the linkage and the java native definition is compatible?

And also, I want to figure out a way to implement a type checking like this. I already know that I can use dlopen()/dlsym()/dlclose() on Linux Platform, but it cannot acquire the type descriptor, and because of that, I cannot proceed the type checking. Is there any other way to load dynamic library and symbols with type descriptors?

I'm going to implement this library loading and type checking in a "wheel" project we made called JustVM, repo's here:
https://github.com/lfkdsk/JustVM


Solution

  • JVM does not enforce type safety of native methods. It only cares about the name.

    E.g. the following code will compile fine, and the library will be successfully loaded. However, when you call nativeMethod, JVM will crash, because it will treat return value -1 as an Object.

    Test.java

    public class Test {
    
        public static void main(String[] args) throws Exception {
            System.loadLibrary("test");
            new Test().nativeMethod(0, 1);
        }
    
        private native Object nativeMethod(long a, int b);
    }
    

    test.c

    #include <jni.h>
    
    JNIEXPORT jint JNICALL Java_Test_nativeMethod(JNIEnv* env, jobject self) {
        return -1;
    }
    

    If you want to retain information about argument types for dynamic linking, you'll have to encode it somehow in the function name. See Name mangling.