使用 jni 调用时 jvm 如何检查参数和 return 类型?如何实现这种类型检查?

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

JNI 规范要求函数必须放在 extern "C" 块中。但是 C 链接不包含类型描述符。因此,当您在 java 代码中调用本地方法时,jvm 如何检查链接中本地代码的参数 number/order/type 和 return 类型以及 java 本地定义兼容吗?

而且,我想找出一种方法来实现这样的类型检查。我已经知道我可以在 Linux 平台上使用 dlopen()/dlsym()/dlclose(),但是它无法获取类型描述符,因此我无法进行类型检查。有没有其他方法可以使用类型描述符加载动态库和符号?

我将在一个名为 JustVM 的 "wheel" 项目中实现这个库加载和类型检查,repo 在这里:
https://github.com/lfkdsk/JustVM

JNI specification require the function must be placed in extern "C" block. But C linkage doesn't contain a type descriptor.

但是 javah 生成的函数名可以。

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?

因为这就是它要查找的内容,它会根据所需的参数等重新生成名称,如果找不到则抛出 LinkageError

And also, I want to figure out a way to implement a type checking like this.

照样做。

JVM 不强制本机方法的类型安全。它只关心名字。

例如下面的代码可以正常编译,库也可以成功加载。但是,当您调用 nativeMethod 时,JVM 会崩溃,因为它将 return 值 -1 视为对象。

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;
}

如果您想为动态链接保留有关参数类型的信息,则必须在函数名称中以某种方式对其进行编码。参见 Name mangling