How to influence search path of System.loadLibrary() through Java code?

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.


  1. There is no approved way to 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

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.

(Option 1) Replace the java.library.path

System.setProperty("java.library.path", newPath);
Field field = ClassLoader.class.getDeclaredField("sys_paths");
field.setAccessible(true);
field.set(ClassLoader.getSystemClassLoader(), new String[]{newPath});

(Option 2) Add to existing java.library.path

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()]));