Rae*_*ald 2 java java-native-interface shared-libraries classloader
如果您想要加载一个类的多个版本,如果它们实现了共享接口并且位于单独的 JAR 中,则可以为每个版本使用单独的类加载器来执行此操作。
如果您有一个调用本机代码的 JAR,则可以将本机代码的共享库 (DLL) 存储在其 JAR 中,方法是将共享库提取到临时文件,然后使用System.load从临时文件加载该库。
但如果两者都做,会有效吗?如果两个版本的 JAR 都调用本机代码,并且都包含不同版本的共享库,会发生什么情况?
让我们假设两个 JAR 使用不同的临时文件来存储共享库的副本。但是共享库的两个版本都具有调用具有相同声明的本机 (C) 函数的本机代码(但这些函数的实现不同)。JVM/类加载器/会将System.load Java 代码委托给正确的本机代码吗?或者 JVM 会抱怨名称冲突吗?
如果该方案确实失败,我如何使用使用本机代码的类的多个版本?
检查 Open JDK 7 实现,似乎可以加载使用本机代码的多个版本的 Java 类:
关键信息是,行为如何System.load?该方法的实现将取决于系统,但各种实现的语义应该相同。
System.load委托给包私有方法Runtime.load0。Runtime.load0委托给包私有静态方法ClassLoader.loadLibrary。ClassLoader.loadLibrary委托给私有静态方法ClassLoader.loadLibrary0。ClassLoader.loadLibrary0创建包私有内部类的对象ClassLoader.NativeLibrary并委托给它的load方法。ClassLoader.NativeLibrary.load是一个本机方法,它委托给 function JVM_LoadLibrary。JVM_LoadLibrary代表到os::dll_load.os::dll_load是系统相关的。os::dll_load委托给dlopen系统调用,提供RTLD_LAZY选项。dlopenRTLD_LOCALRTLD_LOCALRTLD_LOCAL语义是加载的库中的符号不可用于后续加载的库的(自动)符号解析。也就是说,符号不进入全局命名空间,不同的库可以定义相同的符号而不会产生冲突。共享库甚至可以具有相同的内容而不会出现问题。extern:JRE 和 JVM 一起避免名称冲突。这确保了共享库的多个版本不会产生名称冲突。但是 OpenJDK 如何确保本地方法调用使用正确的JNI 代码呢?
SharedRuntime::generate_native_wrapper。然而,最终需要知道要调用的 JNI 函数的地址。methodHandle获取 JNI 函数的地址。methodHandle::critical_native_function()methodHandle::native_function()methodHandle调用methodHandle::set_native_functionfrom记录在 中NativeLookup::lookup。NativeLookup::lookup代表间接地NativeLookup::lookup_styleNativeLookup::lookup_style委托给 Java 包私有静态方法ClassLoader.findNative。ClassLoader.findNative按照加载库的顺序迭代由设置的对象列表 ( ClassLoader.nativeLibraries) 。对于每个库,它委托尝试找到感兴趣的本机方法。虽然这个对象列表不是公开的,但JNI 规范要求 JVM“为每个类加载器维护一个已加载的本机库的列表”,因此所有实现都必须具有与此列表类似的内容。ClassLoader.NativeLibraryClassLoader.loadLibrary0NativeLibrary.findNativeLibrary.find是一个本机方法。它只是委托给JVM_FindLibraryEntry.JVM_FindLibraryEntry委托给系统相关方法os::dll_lookup。os::dll_lookup委托dlsym系统调用来查找共享库中函数的地址。| 归档时间: |
|
| 查看次数: |
2759 次 |
| 最近记录: |