javajava-native-interfacenative

Adding new paths for native libraries at runtime in Java


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 ?


Solution

  • [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);
    }