Is it possible to add a new path for native libraries at runtime ?.
(Instead of starting Java with the property java.library.path), so a call to System.loadLibrary(nativeLibraryName)
will include that path when trying to find nativeLibraryName
.
Is that possible or these paths are frozen once the JVM has started ?
Asked
Active
Viewed 1.8k times
18

Sergio
- 8,532
- 11
- 52
- 94
-
http://stackoverflow.com/questions/2899804/setting-classpath-during-runtime – Subir Kumar Sao Mar 14 '13 at 12:35
2 Answers
30
[This solution don't work with Java 10+]
It seems impossible without little hacking (i.e. accessing private fields of the ClassLoader class)
This blog provide 2 ways of doing it.
For the record, here is the short version.
Option 1: fully replace java.library.path with the new value)
public static void setLibraryPath(String path) throws Exception {
System.setProperty("java.library.path", path);
//set sys_paths to null so that java.library.path will be reevalueted next time it is needed
final Field sysPathsField = ClassLoader.class.getDeclaredField("sys_paths");
sysPathsField.setAccessible(true);
sysPathsField.set(null, null);
}
Option 2: add a new path to the current java.library.path
/**
* Adds the specified path to the java library path
*
* @param pathToAdd the path to add
* @throws Exception
*/
public static void addLibraryPath(String pathToAdd) throws Exception{
final Field usrPathsField = ClassLoader.class.getDeclaredField("usr_paths");
usrPathsField.setAccessible(true);
//get array of paths
final String[] paths = (String[])usrPathsField.get(null);
//check if the path to add is already present
for(String path : paths) {
if(path.equals(pathToAdd)) {
return;
}
}
//add the new path
final String[] newPaths = Arrays.copyOf(paths, paths.length + 1);
newPaths[newPaths.length-1] = pathToAdd;
usrPathsField.set(null, newPaths);
}

ben75
- 29,217
- 10
- 88
- 134
-
1indeed quite a hack :) thanks for posting it. It should not be that hacky, probably it is difficult to change that path for security reasons, not sure. I will avoid to do this but it is nice to know it exists. – Sergio Mar 14 '13 at 12:40
-
1
-
3
-
1Is there a better way to do this in Java-9 or Java-10? This type of reflective access results in a warning or exception in the former and is not permitted in the latter. – drwatsoncode Aug 04 '18 at 04:33
9
I used this in Java 12/13 which should work for any JVM with MethodHandles:
Lookup cl = MethodHandles.privateLookupIn(ClassLoader.class, MethodHandles.lookup());
VarHandle sys_paths = cl.findStaticVarHandle(ClassLoader.class, "sys_paths", String[].class);
sys_paths.set(null);
It has the benefit of being a Java API.
It is replaces the:
final Field sysPathsField = ClassLoader.class.getDeclaredField("sys_paths");
sysPathsField.setAccessible(true);
sysPathsField.set(null, null);

Matthew Gerring
- 99
- 1
- 2
-
4This has also stopped working with JDK 16. I am thinking there is no more solution to this - the clean way is to use System.load. – Stefan Reich Oct 08 '21 at 17:50
-
The best way is to stick to older versions of java and do the hack... it is quite clear there are no good things in latest java except more restrictions that choke developers – D. Sikilai Feb 06 '22 at 07:29