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:
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?
The library path environment variable tells Java™ applications that run on AIX® and Linux®, such as the JVM, where to find shared libraries. The location of shared libraries is important when they are located in a different directory from the directory that is specified in the header section of the program.
The System. load() method takes as a parameter a fully qualified path to the native library and loads the specified native library. The System. loadLibrary() takes as parameter a library name, locates a native library that corresponds to that name, and loads the native library.
java. library. path is a System property, which is used by Java programming language, mostly JVM, to search native libraries, required by a project. Similar to PATH and Classpath environment variable, java.
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.
Based on your comments above (particularly, the behavior of the 3rd-party library), I'd say that your best option is to get the library path right when you launch the JVM.
Note that there is a hacky way to change the library path (see https://stackoverflow.com/a/24258955/139985) but it involves nasty reflection, and it reportedly doesn't work for all Java releases. Certainly, it relies on undocumented private implementation details of ClassLoader
that could change from one release to the next.
Just recently ran into this issue and using OpenJDK where a NullPointerException
is thrown (as @0-0 mentioned in his comment to Samil's answer). The following works in OpenJDK and should work with Oracle JDK as well.
System.setProperty("java.library.path", newPath);
Field field = ClassLoader.class.getDeclaredField("sys_paths");
field.setAccessible(true);
field.set(ClassLoader.getSystemClassLoader(), new String[]{newPath});
String libPath = System.getProperty("java.library.path");
String newPath;
if (libPath == null || libPath.isEmpty()) {
newPath = path;
} else {
newPath = path + File.pathSeparator + libPath;
}
System.setProperty("java.library.path", newPath);
Field field = ClassLoader.class.getDeclaredField("sys_paths");
field.setAccessible(true);
// Create override for sys_paths
ClassLoader classLoader = ClassLoader.getSystemClassLoader();
List<String> newSysPaths = new ArrayList<>();
newSysPaths.add(path);
newSysPaths.addAll(Arrays.asList((String[])field.get(classLoader)));
field.set(classLoader, newSysPaths.toArray(new String[newSysPaths.size()]));
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());
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With