【问题标题】:Difference between using java.library.path and LD_LIBRARY_PATH使用 java.library.path 和 LD_LIBRARY_PATH 的区别
【发布时间】:2015-03-12 18:34:35
【问题描述】:

设置JVM参数有区别吗

-Djava.library.path=/path 

在 JVM 启动和设置 Linux 环境变量时

export LD_LIBRARY_PATH=/path 

在JVM启动之前?

这两种方法的优缺点是什么?

【问题讨论】:

    标签: java linux java-native-interface shared-libraries


    【解决方案1】:

    Java 可以显式加载以-Djava.library.path=... 列出的库 如 alijandro 所述。

    例如,如果 mq series 用于绑定模式,则可以使用 -Djava.library.path=/opt/mq/java/lib 指定所需库的路径,然后 mqseries 加载库。

    如果一个库不是从 java 中明确加载的,即必须使用依赖库,则必须使用 LD_LIBRARY_PATH 使该库在 jvm 中可用。

    【讨论】:

      【解决方案2】:

      第一种形式

      -Djava.library.path=/path
      

      将在 java 字节码级别处理,System.loadLibrary 将调用Runtime.loadLibary,然后将调用java/lang/ClassLoader.loadLibrary。在函数调用ClassLoader.loadLibrary中,会检查系统属性java.library.path获取库的全路径,并将该全路径传递给native code调用系统apidlopen/dlsym,最终使库加载。您可以从OpenJDK 存储库浏览源代码。以下代码 sn -p 是我从链接中复制的段。

      这种形式的好处是,如果你的库路径有问题,你会在Java代码中得到错误或警告或异常。

      // Invoked in the java.lang.Runtime class to implement load and loadLibrary.
      static void loadLibrary(Class fromClass, String name,
                              boolean isAbsolute) {
          ClassLoader loader =
              (fromClass == null) ? null : fromClass.getClassLoader();
          if (sys_paths == null) {
              usr_paths = initializePath("java.library.path");
              sys_paths = initializePath("sun.boot.library.path");
          }
          if (isAbsolute) {
              if (loadLibrary0(fromClass, new File(name))) {
                  return;
              }
              throw new UnsatisfiedLinkError("Can't load library: " + name);
          }
      // ....
      

      第二种形式

      export LD_LIBRARY_PATH=/path
      

      会按照dlopen/dlsym的文档以native方式处理

       dlopen()
         The function dlopen() loads the dynamic library file named by the null-terminated string filename and returns an opaque  "handle"  for  the
         dynamic  library.   If  filename is NULL, then the returned handle is for the main program.  If filename contains a slash ("/"), then it is
         interpreted as a (relative or absolute) pathname.  Otherwise, the dynamic linker searches for the library as follows (see ld.so(8) for fur‐
         ther details):
      
         o   (ELF  only)  If  the  executable  file for the calling program contains a DT_RPATH tag, and does not contain a DT_RUNPATH tag, then the
             directories listed in the DT_RPATH tag are searched.
      
         o   If, at the time that the program was started, the environment variable LD_LIBRARY_PATH was defined to contain a colon-separated list of
             directories, then these are searched.  (As a security measure this variable is ignored for set-user-ID and set-group-ID programs.)
      

      这样,如果你的库路径有问题,系统无法加载你的库,系统不会给出太多线索,会默默地失败(我猜)。要看是否实现LD_LIBRARY_PATH,Android没有使用LD_LIBRARY_PATH来确定库位置,可以从here看到Android的实现。

      【讨论】:

      • 值得注意的是(但正如您可能从这种差异中所期望的那样),加载引用其他库的本机库(ala -lboost 或其他)不会在 @987654336 中找到引用的库@,但$LD_LIBRARY_PATH中找到它们。
      • 在 Linux 系统上(在 Centos 上尝试过),LD_LIBRARY_PATH 的值在 java.library.path 系统属性中被前置。在我的 MacOS 上不会发生这种情况
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-01-20
      • 2012-11-17
      • 1970-01-01
      • 2010-12-26
      • 2012-08-26
      • 2013-12-02
      • 1970-01-01
      相关资源
      最近更新 更多