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

前端 未结 6 1079
一向
一向 2021-02-04 03:18

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

相关标签:
6条回答
  • 2021-02-04 03:47
    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.

    0 讨论(0)
  • 2021-02-04 03:55

    While technically correct these answers are missleading. Setting the environment variables PATH on Windows, or LD_LIBRARY_PATH on unix will change where the jvm looks for libraries: What is LD_LIBRARY_PATH and how to use it?

    on linux: export LD_LIBRARY_PATH=/usr/.../ then: java ....

    0 讨论(0)
  • 2021-02-04 03:56

    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.

    0 讨论(0)
  • 2021-02-04 03:56

    Just recently ran into this issue and using OpenJDK where a NullPointerException is thrown (as 0-0 mentioned the 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()]));
    
    0 讨论(0)
  • 2021-02-04 03:56

    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.

    0 讨论(0)
  • 2021-02-04 03:57

    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());
    
    0 讨论(0)
提交回复
热议问题