RFR(S): 8191360: Lookup of critical JNI method causes duplicate library loading with leaking handler
david.holmes at oracle.com
Tue Dec 5 06:30:19 UTC 2017
On 5/12/2017 4:27 PM, Tobias Hartmann wrote:
> Hi David,
> thanks for the review!
> On 04.12.2017 22:46, David Holmes wrote:
>> I'm unclear why you added the critical entry to test/jdk/java/lang/ClassLoader/nativeLibrary/libnativeLibraryTest.c ??
>> The impact of that on the test is not clear to me. It also obscures whether the test is fixed just by the actual fix.
> Right, I should have mentioned that in the RFR. The reason is that I first had a fix that only unloaded the shared
> library if no critical method was found, i.e., if critical_entry == NULL. This fixes the crash in the original test
> (because there is no critical version of the method). For additional coverage, I've added a critical entry to the test
> Thinking about it again, the test changes are not necessary. Here's a webrev without:
>> I agree with Vladimir that there is scope for being more efficient with the library handling in this code, but that's
>> future work.
> Right, I'll file a separate RFE and link it to the bug.
> Best regards,
>>> When creating a native wrapper, the compiler checks the shared library for a critical version of the native method
>>> (-XX:+CriticalJNINatives, see comments in JDK-7013347 ) that can be called with reduced overhead. This is done in
>>> NativeLookup::lookup_critical_style() with a call to dll_load() to get a handle to the (already loaded) library and a
>>> subsequent call to dll_lookup() to get the entry address of the critical version.
>>> The problem is that without a call to dll_unload(), this handle to the library will stay live and internal reference
>>> counting will prevent the library from ever being unloaded (even if the native method holder is unloaded). As a result,
>>> static fields in the library code are not reset, causing the NativeLibraryTest to fail due to unexpected field values
>>> once the library is loaded again.
>>> I've fixed this by closing the handle immediately after retrieving the critical entry address. This is fine because the
>>> library is still kept alive by JNI (see JVM_LoadLibrary). As soon as the holder class and the library are unloaded (see
>>> JVM_UnloadLibrary), the native wrapper that calls 'critical_entry' becomes unreachable and is unloaded as well.
>>> I've also thought about passing 'RTLD_NOLOAD' to dlopen  but although that avoids loading the library, it still
>>> creates a handle (that needs to be closed) if the library is already loaded.
>>> Tested with failing test and Mach 5 hs-tier1, hs-tier2, hs-precheckin-comp (running).
>>>  https://bugs.openjdk.java.net/browse/JDK-7013347
>>>  https://linux.die.net/man/3/dlopen
More information about the hotspot-dev