Certain Java APIs are caller-sensitive. One (woefully underdocumented IMO) example is System.load()
, which loads some JNI code into the caller's ClassLoader
only.
I have a wrapper that looks roughly like JniUtils.loadLibrary("nameoflibrary")
. It finds the appropriate library for the current architecture, extracts it out of the JAR, and passes it to System.load()
. But I just ran into a case where the caller of JniUtils.loadLibrary
wasn't in the same ClassLoader
as Jni
itself. That caused the library to get loaded into the wrong ClassLoader
, resulting in UnsatisfiedLinkError
once the native methods got called.
Without relying on JVM internals like sun.reflect.Reflection.getCallerClass()
, is there a way to work around this issue? My current idea is to change the wrapper like this:
public class JniUtils {
public static void loadLibrary(String libraryName, MethodHandles.Lookup lookup);
}
which can be called like this:
public class NeedsJni {
static {
JniUtils.loadLibrary("nameoflibrary", MethodHandles.lookup());
}
}
Using the Lookup
to resolve and call the System.load()
method should preserve NeedsJni
as the caller.
Is there a better workaround?
Aucun commentaire:
Enregistrer un commentaire