Incorrect return value for Java_jdk_internal_loader_NativeLibraries_load() in java.base/share/native/libjava/NativeLibraries.c
Cheng Jin
jincheng at ca.ibm.com
Thu Feb 24 00:08:30 UTC 2022
Hi there,
The return value from Java_jdk_internal_loader_NativeLibraries_load() at https://github.com/openjdk/jdk/blob/master/src/java.base/share/native/libjava/NativeLibraries.c
seems incorrect according to the code logic in there.
Looking at the calling path from loadLibrary() to load() at src/java.base/share/classes/jdk/internal/loader/NativeLibraries.java as follows:
public NativeLibrary loadLibrary(Class<?> fromClass, String name) {
...
NativeLibrary lib = findFromPaths(LibraryPaths.SYS_PATHS, fromClass, name); <----------
if (lib == null && searchJavaLibraryPath) {
lib = findFromPaths(LibraryPaths.USER_PATHS, fromClass, name); <----
}
return lib;
}
private NativeLibrary findFromPaths(String[] paths, Class<?> fromClass, String name) {
for (String path : paths) { <---------------- keep searching the library paths till the library is located at the correct lib path
File libfile = new File(path, System.mapLibraryName(name));
NativeLibrary nl = loadLibrary(fromClass, libfile); ?
if (nl != null) {
return nl; <--------------------
}
libfile = ClassLoaderHelper.mapAlternativeName(libfile);
if (libfile != null) {
nl = loadLibrary(fromClass, libfile);
if (nl != null) {
return nl;
}
}
}
return null;
}
public NativeLibrary loadLibrary(Class<?> fromClass, File file) {
// Check to see if we're attempting to access a static library
String name = findBuiltinLib(file.getName());
boolean isBuiltin = (name != null);
...
return loadLibrary(fromClass, name, isBuiltin); <------------
}
private NativeLibrary loadLibrary(Class<?> fromClass, String name, boolean isBuiltin) {
...
NativeLibraryImpl lib = new NativeLibraryImpl(fromClass, name, isBuiltin, isJNI);
// load the native library
NativeLibraryContext.push(lib);
try {
if (!lib.open()) { <--------------------- call load()
return null; // fail to open the native library
}
...
// register the loaded native library
loadedLibraryNames.add(name);
libraries.put(name, lib);
return lib; <--------------- return an invalid lib as lib.open() returns true
} finally {
releaseNativeLibraryLock(name);
}
...
}
/*
* Loads the named native library
*/
boolean open() {
...
return load(this, name, isBuiltin, isJNI, loadLibraryOnlyIfPresent);
}
private static native boolean load(NativeLibraryImpl impl, String name, boolean isBuiltin, boolean isJNI, boolean throwExceptionIfFail);
and then native code in java.base/share/native/libjava/NativeLibraries.c
Java_jdk_internal_loader_NativeLibraries_load
(JNIEnv *env, jobject this, jobject lib, jstring name,
jboolean isBuiltin, jboolean isJNI, jboolean throwExceptionIfFail)
{
const char *cname;
jint jniVersion;
jthrowable cause;
void * handle;
jboolean loaded = JNI_FALSE;
...
handle = isBuiltin ? procHandle : JVM_LoadLibrary(cname, throwExceptionIfFail);
if (isJNI) {
...
}
(*env)->SetLongField(env, lib, handleID, ptr_to_jlong(handle));
loaded = JNI_TRUE; <----- always return true when isJNI is false and a null handle
done:
JNU_ReleaseStringPlatformChars(env, name, cname);
return loaded;
}
Assuming there are multiple library paths existing in the jdk/lib which are added to sun.boot.library.path and java.library.path
and the expected library (libnative.so) is only placed in jdk/lib. e.g.
lib/libA
lib/libB
lib/libC
lib/libnative.so
when the code in findFromPaths() searches the library paths set in sun.boot.library.path and java.library.path starting from lib/LibA,
it will end up with an invalid value if load() returns true in the case of a false isJNI and a null handle returned from JVM_LoadLibrary()
as the library doesn't exist in lib/libA passed to JVM_LoadLibrary().
To ensure findFromPaths() keeps searching the remaining lib paths, the simple fix should look like:
Java_jdk_internal_loader_NativeLibraries_load( ...)
{
...
(*env)->SetLongField(env, lib, handleID, ptr_to_jlong(handle));
if (handle) { <------------------------- return true only for a non-null handle
loaded = JNI_TRUE;
}
...
}
Please help check the code around there to see whether the fix is reasonable to avoid the unexpected situation as explained above (the problem was spotted since JDK17)
Best Regards
Cheng Jin
More information about the core-libs-dev
mailing list