Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

8282515: More clean up on NativeLibraries just for JNI library use #7661

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
@@ -190,7 +190,7 @@ private NativeLibrary loadLibrary(Class<?> fromClass, String name, boolean isBui
}
}

NativeLibraryImpl lib = new NativeLibraryImpl(fromClass, name, isBuiltin, true);
NativeLibraryImpl lib = new NativeLibraryImpl(fromClass, name, isBuiltin);
// load the native library
NativeLibraryContext.push(lib);
try {
@@ -290,21 +290,16 @@ static class NativeLibraryImpl implements NativeLibrary {
final String name;
// Indicates if the native library is linked into the VM
final boolean isBuiltin;
// Indicate if this is JNI native library
final boolean isJNI;

// opaque handle to native library, used in native code.
long handle;
// the version of JNI environment the native library requires.
int jniVersion;

NativeLibraryImpl(Class<?> fromClass, String name, boolean isBuiltin, boolean isJNI) {
assert !isBuiltin || isJNI : "a builtin native library must be JNI library";

NativeLibraryImpl(Class<?> fromClass, String name, boolean isBuiltin) {
this.fromClass = fromClass;
this.name = name;
this.isBuiltin = isBuiltin;
this.isJNI = isJNI;
}

@Override
@@ -322,7 +317,7 @@ public long find(String name) {
* when this class loader becomes phantom reachable.
*/
private Runnable unloader() {
return new Unloader(name, handle, isBuiltin, isJNI);
return new Unloader(name, handle, isBuiltin);
}

/*
@@ -333,14 +328,14 @@ boolean open() {
throw new InternalError("Native library " + name + " has been loaded");
}

return load(this, name, isBuiltin, isJNI, loadLibraryOnlyIfPresent);
return load(this, name, isBuiltin, loadLibraryOnlyIfPresent);
}

/*
* Close this native library.
*/
void close() {
unload(name, isBuiltin, isJNI, handle);
unload(name, isBuiltin, handle);
}
}

@@ -352,15 +347,13 @@ static class Unloader implements Runnable {
// This represents the context when a native library is unloaded
// and getFromClass() will return null,
static final NativeLibraryImpl UNLOADER =
new NativeLibraryImpl(null, "dummy", false, false);
new NativeLibraryImpl(null, "dummy", false);

final String name;
final long handle;
final boolean isBuiltin;
final boolean isJNI;

Unloader(String name, long handle, boolean isBuiltin, boolean isJNI) {
assert !isBuiltin || isJNI : "a builtin native library must be JNI library";
Unloader(String name, long handle, boolean isBuiltin) {
if (handle == 0) {
throw new IllegalArgumentException(
"Invalid handle for native library " + name);
@@ -369,20 +362,19 @@ static class Unloader implements Runnable {
this.name = name;
this.handle = handle;
this.isBuiltin = isBuiltin;
this.isJNI = isJNI;
}

@Override
public void run() {
acquireNativeLibraryLock(name);
try {
/* remove the native library name */
if (isJNI && !loadedLibraryNames.remove(name)) {
if (!loadedLibraryNames.remove(name)) {
throw new IllegalStateException(name + " has already been unloaded");
}
NativeLibraryContext.push(UNLOADER);
try {
unload(name, isBuiltin, isJNI, handle);
unload(name, isBuiltin, handle);
} finally {
NativeLibraryContext.pop();
}
@@ -524,12 +516,28 @@ private static Class<?> getFromClass() {
return NativeLibraryContext.peek().fromClass;
}

// JNI FindClass expects the caller class if invoked from JNI_OnLoad
// and JNI_OnUnload is NativeLibrary class
/*
* Return true if the given library is successfully loaded.
* If the given library cannot be loaded for any reason,
* if throwExceptionIfFail is false, then this method returns false;
* otherwise, UnsatisfiedLinkError will be thrown.
*
* JNI FindClass expects the caller class if invoked from JNI_OnLoad
* and JNI_OnUnload is NativeLibrary class.
*/
private static native boolean load(NativeLibraryImpl impl, String name,
boolean isBuiltin, boolean isJNI,
boolean isBuiltin,
boolean throwExceptionIfFail);
private static native void unload(String name, boolean isBuiltin, boolean isJNI, long handle);
/*
* Unload the named library. JNI_OnUnload, if present, will be invoked
* before the native library is unloaded.
*/
private static native void unload(String name, boolean isBuiltin, long handle);
private static native String findBuiltinLib(String name);
private static native long findEntry0(NativeLibraryImpl lib, String name);

/*
* Returns the address of the named symbol defined in the given library.
* Returns 0 if not found.
*/
static native long findEntry0(NativeLibrary lib, String name);
}
@@ -48,7 +48,7 @@
* 3. No relationship with class loaders.
*/
public final class RawNativeLibraries {
final Map<String, NativeLibraryImpl> libraries = new ConcurrentHashMap<>();
final Map<String, RawNativeLibraryImpl> libraries = new ConcurrentHashMap<>();
final Class<?> caller;

private RawNativeLibraries(MethodHandles.Lookup trustedCaller) {
@@ -116,10 +116,10 @@ public NativeLibrary load(String pathname) {
return libraries.computeIfAbsent(pathname, this::get);
}

private NativeLibraryImpl get(String pathname) {
NativeLibraryImpl lib = new NativeLibraryImpl(caller, pathname, false, false);
private RawNativeLibraryImpl get(String pathname) {
RawNativeLibraryImpl lib = new RawNativeLibraryImpl(caller, pathname);
if (!lib.open()) {
return null; // fail to open the native library
return null;
}
return lib;
}
@@ -132,8 +132,49 @@ public void unload(NativeLibrary lib) {
if (!libraries.remove(lib.name(), lib)) {
throw new IllegalArgumentException(lib.name() + " not loaded by this RawNativeLibraries instance");
}
NativeLibraryImpl nl = (NativeLibraryImpl)lib;
RawNativeLibraryImpl nl = (RawNativeLibraryImpl)lib;
nl.close();
}

static class RawNativeLibraryImpl implements NativeLibrary {
// the name of the raw native library.
final String name;
// opaque handle to raw native library, used in native code.
long handle;

RawNativeLibraryImpl(Class<?> fromClass, String name) {
this.name = name;
}

@Override
public String name() {
return name;
}

@Override
public long find(String name) {
return findEntry0(this, name);
}

/*
* Loads the named native library.
*/
boolean open() {
if (handle != 0) {
throw new InternalError("Native library " + name + " has been loaded");
}
return load0(this, name);
}

/*
* Close this native library.
*/
void close() {
unload0(name, handle);
}
}

private static native boolean load0(RawNativeLibraryImpl impl, String name);
private static native void unload0(String name, long handle);
}