问题描述:

In a Java project, I am using a third-party library that loads some native library via

System.loadLibrary("libName");

I'd like to be able to influence the search path of this method from within my application, so that the user doesn't need to specify a correct java.library.path value on the command line (this value depends on the current OS and architecture). E.g on Windows I want to set it to "lib/native/windows", on Linux 32bit to "lib/native/linux32" etc.

I tried

System.setProperty("java.library.path", ...)

but this is ignored, apparently because the JVM reads this property only once before my code is run.

I also tried to load the native libray before using the Java library that depends on it with

System.load("fullPath/lib")

This call succeeds, but there will still be an UnsatisfiedLinkError when the native library is loaded again with System.loadLibrary().

The only way I found is the following:

  • Add interfaces that abstract the whole API of the external library.
  • Use only these interfaces in the rest of the code.
  • Add classes that implement the interfaces and delegate to the library.
  • Write an own ClassLoader, that

    • overwrites findLibary() so that the native library is found in the correct path
    • overwrites loadClass() and loads all classes of the external library and the wrapper layer by itself instead of trying to delegate to its parent like the default ClassLoader would do
  • Ensure that the interfaces are loaded with the normal ClassLoader and the wrapping classes and the external library are loaded with my own ClassLoader.

This works, but I find it very complicated and it is much effort because I need to add all those interfaces. Is there a simpler way?

网友答案:
  1. You cannot change the library path for a running JVM.
  2. You cannot load a native library more than once ... and you cannot unload a native library so that you can load it again: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4171986

Base on your comments above (particularly, the behaviour of the 3rd-party library), I'd say that your best option is to get the library path right when you launch the JVM.

网友答案:

I needed to change the dll path for my unit tests. I tried the following hack and it worked:

System.setProperty( "java.library.path", "/path/to/libs" ); 
Field fieldSysPath = ClassLoader.class.getDeclaredField( "sys_paths" );
fieldSysPath.setAccessible( true );
fieldSysPath.set( null, null );

For explanation, see the original link.

网友答案:

I tried to following to load a native Growl library for a Java application on my Mac where the lib is in the root of the classpath of my application:

System.load(GrowlUtils.class.getResource("/libgrowl.jnilib").getFile().toString());
网友答案:

Is there a simpler way?

Yes, provide batch/script files to start the application. Then you can set the correct path in the batch/shell file or even read the value from an environment variable. Much easier then trying to do it from inside the application.

相关阅读:
Top