使用java.library.path和LD_LIBRARY_PATH之间的区别

设置 JVM 参数之间是否有区别

-Djava.library.path=/path 

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

export LD_LIBRARY_PATH=/path 

在 JVM 启动之前?

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


答案 1

第一种形式

-Djava.library.path=/path

将在java字节码级别处理,将调用,然后调用。在函数调用中,系统属性将被检查以获得库的完整路径,并将这个完整路径传递给本地代码来调用系统api,最终使库加载。您可以从 OpenJDK 存储库浏览源代码。以下代码片段是我从链接复制的段。System.loadLibraryRuntime.loadLibaryjava/lang/ClassLoader.loadLibraryClassLoader.loadLibraryjava.library.pathdlopen/dlsym

此表单的优点是,如果您的库路径存在一些问题,您将在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.)

通过这种方式,如果您的库路径存在一些问题,并且系统无法加载您的库,则系统不会提供太多线索,并且会默默地失败(我猜)。这取决于是否实现,Android没有用来确定库的位置,你可以从这里看到Android的实现。LD_LIBRARY_PATHLD_LIBRARY_PATH


答案 2

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

例如,如果在绑定模式下使用 mq 系列,则可以使用 指定必要库的路径,并且 mqseries 加载这些库。-Djava.library.path=/opt/mq/java/lib

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


推荐