Hi Aleksei,
On 11/05/2021 11:19 pm, Aleksei Voitylov wrote:
Please review this PR which fixes the deadlock in ClassLoader between the two
lock objects - a lock object associated with the class being loaded, and the
ClassLoader.loadedLibraryNames hash map, locked during the native library load
operation.
Problem being fixed:
The initial reproducer demonstrated a deadlock between the JarFile/ZipFile and
the hash map. That deadlock exists even when the ZipFile/JarFile lock is
removed because there's another lock object in the class loader, associated
with the name of the class being loaded. Such objects are stored in
ClassLoader.parallelLockMap. The deadlock occurs when JNI_OnLoad() loads
exactly the same class, whose signature is being verified in another thread.
Proposed fix:
The proposed patch suggests to get rid of locking loadedLibraryNames hash map
and synchronize on each entry name, as it's done with class names in see
ClassLoader.getClassLoadingLock(name) method.
The ClassLoader per-name locking map has a number of problems so I'm not
sure using it as a model is a good idea. In particular your new map only
grows, with entries never being removed AFAICS.
This is a difficult deadlock to solve. Even using a per-entry lock it
isn't obvious to me that you can't still get a deadlock.
My own thoughts on this problem were that we should not be calling
JNI_OnLoad with any lock held. But that risks use of a library in a
separate thread before the JNI+OnLoad has completed. As I said this is a
difficult deadlock to solve - and may not have a complete solution.
David
-----
The patch introduces nativeLibraryLockMap which holds the lock objects for each
library name, and the getNativeLibraryLock() private method is used to lazily
initialize the corresponding lock object. nativeLibraryContext was changed to
ThreadLocal, so that in any concurrent thread it would have a NativeLibrary
object on top of the stack, that's being currently loaded/unloaded in that
thread. nativeLibraryLockMap accumulates the names of all native libraries
loaded - in line with class loading code, it is not explicitly cleared.
Testing: jtreg and jck testing with no regressions. A new regression test was
developed.
-------------
Commit messages:
- JDK-8266310: deadlock while loading the JNI code
- JDK-8266310: deadlock while loading the JNI code
Changes: https://git.openjdk.java.net/jdk/pull/3976/files
Webrev: https://webrevs.openjdk.java.net/?repo=jdk&pr=3976&range=00
Issue: https://bugs.openjdk.java.net/browse/JDK-8266310
Stats: 475 lines in 6 files changed: 456 ins; 0 del; 19 mod
Patch: https://git.openjdk.java.net/jdk/pull/3976.diff
Fetch: git fetch https://git.openjdk.java.net/jdk pull/3976/head:pull/3976
PR: https://git.openjdk.java.net/jdk/pull/3976