如果您想加载一个类的多个版本,那么如果它们实现了一个共享接口,并且是在单独的JAR( 对每个版本使用单独的类加载器 )中,则可以这样做。
如果有一个调用本机代码的JAR,则可以在其JAR 从临时文件加载库中存储其本机代码的共享库(DLL)。
但如果两者兼而有之,会成功吗?如果JAR的两个版本都调用本机代码,并且都包含不同版本的共享库,会发生什么情况?
假设两个JAR使用不同的临时文件来存储共享库的副本。但是共享库的两个版本都有本机代码,它们调用具有相同声明的本机(C)函数(但这些函数的实现不同)。JVM/类加载器/System.load
将从Java代码委托给正确的本机代码吗?或者JVM会抱怨名称冲突吗?
如果该方案确实失败,如何使用I使用使用本机代码的类的多个版本?
发布于 2016-10-14 05:08:11
在检查Open 7实现时,似乎是的,加载使用本机代码的多个版本的将工作:
库加载
关键的信息是,System.load
是如何表现的?该方法的实现将依赖于系统,但各种实现的语义应该是相同的。
System.load
委托给包-私有方法Runtime.load0
。Runtime.load0
委托给包-私有静态方法ClassLoader.loadLibrary
。ClassLoader.loadLibrary
将委托给私有静态方法ClassLoader.loadLibrary0
。ClassLoader.loadLibrary0
创建包的对象-私有内部类ClassLoader.NativeLibrary
,并将其委托给它的load
方法。ClassLoader.NativeLibrary.load
是一个本机方法,它将委托给函数JVM_LoadLibrary
。JVM_LoadLibrary
委托给os::dll_load
。os::dll_load
是系统依赖的。os::dll_load
将委托给dlopen
系统调用,从而提供RTLD_LAZY
选项。dlopen
系统调用具有RTLD_LOCAL
行为,因此共享库加载了RTLD_LOCAL
语义。RTLD_LOCAL
语义是指加载库中的符号不能用于随后加载的库的(自动)符号解析。也就是说,符号不进入全局命名空间,不同的库可以在不产生冲突的情况下定义相同的符号。共享库甚至可以毫无问题地拥有相同的内容。。extern
函数名称)并不重要: JRE和JVM共同避免名称冲突。本机函数查找
这确保共享库的多个版本不会产生名称冲突。但是,OpenJDK如何确保本机方法调用使用正确的JNI代码?
SharedRuntime::generate_native_wrapper
中。但是,最终需要知道要调用的JNI函数的地址。methodHandle
C++对象,酌情从methodHandle::critical_native_function()
或methodHandle::native_function()
获取JNI函数的地址。methodHandle
调用methodHandle::set_native_function
记录在NativeLookup::lookup
中。NativeLookup::lookup
间接地委托给NativeLookup::lookup_style
NativeLookup::lookup_style
委托给Java私有静态方法ClassLoader.findNative
。ClassLoader.findNative
按照加载库的顺序遍历ClassLoader.loadLibrary0
设置的ClassLoader.NativeLibrary
对象的列表(ClassLoader.nativeLibraries
)。对于每个库,它委托NativeLibrary.find
尝试查找感兴趣的本机方法。虽然这个对象列表不是公开的,但是JNI规范要求JVM“为每个类加载器维护一个加载的本机库列表”,所以所有实现都必须有类似于这个列表的东西。NativeLibrary.find
是一种本地方法。它只是简单地委托给JVM_FindLibraryEntry
。JVM_FindLibraryEntry
委托给系统相关方法os::dll_lookup
。os::dll_lookup
的Linux实现委托给dlsym
系统调用来查找共享库中函数的地址。发布于 2016-10-14 03:31:31
如果您试图在不同的类加载器中加载相同的库,您将得到一个UnsatisfiedLinkError
,它的消息是“本机库:.已经加载到另一个类加载器中了”。这可能与当类加载器被垃圾收集(方法)时调用库的卸载方法的VM有关。
但是,如果您--正如您所说--“使用不同的临时文件来存储共享库的副本”,那么这两个库实际上是不同的库,而不管文件的内容(可能是二进制相同的,这并不重要)。所以没什么问题。
https://stackoverflow.com/questions/40026804
复制相似问题