Java: load a library that depends on other libs

后端 未结 3 715
孤城傲影
孤城傲影 2021-01-01 06:47

I want to load my own native libraries in my java application. Those native libraries depend upon third-party libraries (which may or may not be present when my application

相关标签:
3条回答
  • 2021-01-01 07:01

    I have successfully implemented something similar for CollabNet Subversion Edge, which depends on the SIGAR libraries across ALL Operating Systems (we support Windows/Linux/Sparc both 32 bits and 64 bits)...

    Subversion Edge is a web application that helps one managing Subversion repositories through a web console and uses SIGAR to the SIGAR libraries helps us provide users data values directly from the OS... You need to update the value of the property "java.library.path" at runtime. (https://ctf.open.collab.net/integration/viewvc/viewvc.cgi/trunk/console/grails-app/services/com/collabnet/svnedge/console/OperatingSystemService.groovy?revision=1890&root=svnedge&system=exsy1005&view=markup Note that the URL is a Groovy code, but I have modified it to a Java here)...

    The following example is the implementation in URL above... (On Windows, your user will be required to restart the machine if he/she has downloaded the libraries after or downloaded them using your application)... The "java.library.path" will update the user's path "usr_paths" instead of System path "sys_paths" (permissions exception might be raised depending on the OS when using the latter).

    133/**
    134 * Updates the java.library.path at run-time.
    135 * @param libraryDirPath
    136 */
    137 public void addDirToJavaLibraryPathAtRuntime(String libraryDirPath) 
    138    throws Exception {
    139    try {
    140         Field field = ClassLoader.class.getDeclaredField("usr_paths");
    141         field.setAccessible(true);
    142         String[] paths = (String[])field.get(null);
    143         for (int i = 0; i < paths.length; i++) {
    144             if (libraryDirPath.equals(paths[i])) {
    145                 return;
    146             }
    147         }
    148         String[] tmp = new String[paths.length+1];
    149         System.arraycopy(paths,0,tmp,0,paths.length);
    150         tmp[paths.length] = libraryDirPath;
    151         field.set(null,tmp);
    152         String javaLib = "java.library.path";
    153         System.setProperty(javaLib, System.getProperty(javaLib) +
    154             File.pathSeparator + libraryDirPath);
    155 
    156     } catch (IllegalAccessException e) {
    157         throw new IOException("Failed to get permissions to set " +
    158             "library path to " + libraryDirPath);
    159     } catch (NoSuchFieldException e) {
    160         throw new IOException("Failed to get field handle to set " +
    161            "library path to " + libraryDirPath);
    162     }
    163 }
    

    The Bootstrap services (Groovy on Grails application) class of the console runs a service and executes it with the full path to the library directory... UNiX-based servers do not need to restart the server to get the libraries, but Windows boxes do need a server restart after the installation. In your case, you would be calling this as follows:

         String appHomePath = "/YOUR/PATH/HERE/TO/YOUR/LIBRARY/DIRECTORY";
         String yourLib = new File(appHomePath, "SUBDIRECTORY/").getCanonicalPath();
    124  try {
    125      addDirToJavaLibraryPathAtRuntime(yourLib);
    126  } catch (Exception e) {
    127      log.error("Error adding the MY Libraries at " + yourLib + " " +
    128            "java.library.path: " + e.message);
    129  }
    

    For each OS you ship your application, just make sure to provide a matching version of the libraries for the specific platform (32bit-Linux, 64bit-Windows, etc...).

    0 讨论(0)
  • 2021-01-01 07:12

    This is a hack used to manipulate JVM's library path programmatically. NOTE: it relies on internals of ClassLoader implementation so it might not work on all JVMs/versions.

    String currentPath = System.getProperty("java.library.path");
    System.setProperty( "java.library.path", currentPath + ":/path/to/my/libs" );
    
    // this forces JVM to reload "java.library.path" property
    Field fieldSysPath = ClassLoader.class.getDeclaredField( "sys_paths" );
    fieldSysPath.setAccessible( true );
    fieldSysPath.set( null, null );
    

    This code uses UNIX-style file path separators ('/') and library path separator (':'). For cross-platform way of doing this use System Properties to get system-specific separators: http://download.oracle.com/javase/tutorial/essential/environment/sysprop.html

    0 讨论(0)
  • 2021-01-01 07:23

    See the accepted answer here:

    Changing LD_LIBRARY_PATH at runtime for ctypes

    In other words, what you're trying to do isn't possible. You'll need to launch a new process with an updated LD_LIBRARY_PATH (e.g., use ProcessBuilder and update environment() to concatenate the necessary directory)

    0 讨论(0)
提交回复
热议问题