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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/27945268/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 12:40:42  来源:igfitidea点击:

Difference between using java.library.path and LD_LIBRARY_PATH

javalinuxjava-native-interfaceshared-libraries

提问by christian

Is there a difference between setting the JVM argument

设置JVM参数有区别吗

-Djava.library.path=/path 

at JVM start and setting the Linux environment variable

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

export LD_LIBRARY_PATH=/path 

before the JVM is started?

在 JVM 启动之前?

What are the advantages/disadvantages of the two approaches?

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

采纳答案by alijandro

The first form

第一种形式

-Djava.library.path=/path

will be handled in java bytecode level, System.loadLibrarywill call Runtime.loadLibary, then will call java/lang/ClassLoader.loadLibrary. In the function call ClassLoader.loadLibrary, the system property java.library.pathwill be checked to get the full path of the library and pass this full path to native code to call system api dlopen/dlsym, eventually make the library loaded. You can browse the source from OpenJDKrepository. The following code snippet is the segment I copy from the link.

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

The advantage of this form is that you will get error or warning or exception in Java code, if there are some problems with your library path.

这种形式的好处是,如果你的库路径有问题,你会在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);
    }
// ....

The second form

第二种形式

export LD_LIBRARY_PATH=/path

will be handled in native, according to the document of dlopen/dlsym

将在本地处理,根据文档 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.)

In this manner, if there are some problems with your library path and the system can't load your library, the system won't give too much clue what happen and will fail silently (I guess). It depends whether or not to implement LD_LIBRARY_PATH, Android didn't use LD_LIBRARY_PATHto determine the library location, you can see Android's implementation from here.

以这种方式,如果您的库路径存在一些问题并且系统无法加载您的库,系统将不会提供太多线索并且会静默失败(我猜)。要看要不要实现LD_LIBRARY_PATH,Android没有LD_LIBRARY_PATH用来判断库位置,可以从这里看Android的实现。

回答by christian

Java can explicitely load libaries listed with -Djava.library.path=...as described by alijandro.

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

For example, if mq series is used in bindings mode, the path for the neccessary libraries can be specified with -Djava.library.path=/opt/mq/java/liband mqseries loads the libraries.

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

If a library is not explcitely loaded from java, i.e. a dependent library has to be used, then LD_LIBRARY_PATHhas to be used to have that library available in the jvm.

如果库不是从 java 显式加载的,即必须使用依赖库,则LD_LIBRARY_PATH必须使用该库才能在 jvm 中使用该库。