使用java.library.path和LD_LIBRARY_PATH有什么区别?

27

设置JVM参数和设置系统属性有什么区别?

-Djava.library.path=/path 

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

export LD_LIBRARY_PATH=/path 

JVM启动前有什么优缺点?

这两种方法各有何优劣之处?

2个回答

22

第一种形式

-Djava.library.path=/path

该操作将在Java字节码级别处理,System.loadLibrary将调用Runtime.loadLibary,然后将调用java/lang/ClassLoader.loadLibrary。在函数调用ClassLoader.loadLibrary中,将检查系统属性java.library.path以获取库的完整路径,并将此完整路径传递给本地代码来调用系统APIdlopen/dlsym,最终使库加载。您可以从OpenJDK存储库中浏览源代码。以下代码片段是我从链接中复制的。

这种形式的优点是,如果您的库路径存在问题,您将在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 文档的要求。

 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来确定库位置,您可以从此处查看Android的实现。

4
值得注意的是(但从这种差异中您可能会预料到),加载引用其他本地库(例如-lboost或其他)_不会_在java.library.path中找到所引用的库,但会在$LD_LIBRARY_PATH中找到它们。 - Rob I
在Linux系统上(我在Centos上尝试过),LD_LIBRARY_PATH的值会被预置在java.library.path系统属性中。但在我的MacOS上,这种情况并不会发生。 - Sa'ad

5
Java可以通过使用-Djava.library.path=...来显式加载列出的库,如alijandro所述。
例如,如果绑定模式中使用了mq系列,则可以使用-Djava.library.path=/opt/mq/java/lib指定必要库的路径,并且mqseries将加载这些库。
如果从Java中未明确加载库,即必须使用依赖库,则必须使用LD_LIBRARY_PATH使该库在jvm中可用。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接