Rui*_*ang 2 java java-native-interface jvm
在阅读JDK源代码时,我发现有些方法是原生的,但是在它们的静态块中没有System.loadLibrary或System.load,那么这些方法实际上是如何加载的?
所以我猜这些方法是内置在 JVM 中的。只是想知道它们是如何为特定类加载的。说,StrictMath。如下:
public final StrictMath {
public static native double cos(double a);
}
Run Code Online (Sandbox Code Playgroud)
所以我可以找到这个本地方法的源代码,只是想知道它是如何为这个特定类加载的。
所有本地方法的绑定在第一次调用时延迟执行,除非这些方法之前通过调用 JNI RegisterNatives函数显式绑定。
因此,在第一次调用本机方法时,JVM 会要求动态链接器查找Java_package_Class_method在其中一个加载的共享库中命名的符号。例如,在 Linux 上调用 来dlsym完成这项工作。
至于StrictMath方法,不需要调用System.loadLibrary,因为带有StrictMath符号的共享库(libjava.so在 Linux 或java.dllWindows 上)已经加载。实际上,JVM 会libjava.so在启动阶段提前加载,因为该库包含 VM 引导所需的核心 Java 方法的本机实现。
检查哪些符号libjava.so包含:
$ nm /usr/java/jdk-11.0.1/lib/libjava.so | grep Java_
....
00000000000146c0 T Java_java_lang_StrictMath_acos
00000000000146b0 T Java_java_lang_StrictMath_asin
00000000000146d0 T Java_java_lang_StrictMath_atan
0000000000014710 T Java_java_lang_StrictMath_atan2
0000000000014680 T Java_java_lang_StrictMath_cos
0000000000014730 T Java_java_lang_StrictMath_cosh
0000000000014770 T Java_java_lang_StrictMath_expm1
...
Run Code Online (Sandbox Code Playgroud)