使用 java.library.path 和 LD_LIBRARY_PATH 的区别
Difference between using java.library.path and LD_LIBRARY_PATH
设置JVM参数有区别吗
-Djava.library.path=/path
在 JVM 启动并设置 Linux 环境变量
export LD_LIBRARY_PATH=/path
在 JVM 启动之前?
这两种方法的advantages/disadvantages是什么?
第一种形式
-Djava.library.path=/path
将在 java 字节码级别处理,System.loadLibrary
将调用 Runtime.loadLibary
,然后将调用 java/lang/ClassLoader.loadLibrary
。在函数调用ClassLoader.loadLibrary
中,会检查系统属性java.library.path
获取库的完整路径,并将此完整路径传递给本机代码调用系统apidlopen/dlsym
,最终使库加载。您可以从 OpenJDK 存储库浏览源代码。以下代码片段是我从 link.
复制的片段
这种形式的优点是,如果您的库路径有问题,您会在 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的实现.
Java 可以明确加载 -Djava.library.path=...
列出的库
正如 alijandro 所述。
比如mq系列使用bindings模式,可以指定需要的库路径-Djava.library.path=/opt/mq/java/lib
,mqseries加载库。
如果库不是从 java 明确加载的,即必须使用依赖库,则必须使用 LD_LIBRARY_PATH
才能在 jvm 中使用该库。
设置JVM参数有区别吗
-Djava.library.path=/path
在 JVM 启动并设置 Linux 环境变量
export LD_LIBRARY_PATH=/path
在 JVM 启动之前?
这两种方法的advantages/disadvantages是什么?
第一种形式
-Djava.library.path=/path
将在 java 字节码级别处理,System.loadLibrary
将调用 Runtime.loadLibary
,然后将调用 java/lang/ClassLoader.loadLibrary
。在函数调用ClassLoader.loadLibrary
中,会检查系统属性java.library.path
获取库的完整路径,并将此完整路径传递给本机代码调用系统apidlopen/dlsym
,最终使库加载。您可以从 OpenJDK 存储库浏览源代码。以下代码片段是我从 link.
这种形式的优点是,如果您的库路径有问题,您会在 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
判断库位置,可以从here看Android的实现.
Java 可以明确加载 -Djava.library.path=...
列出的库
正如 alijandro 所述。
比如mq系列使用bindings模式,可以指定需要的库路径-Djava.library.path=/opt/mq/java/lib
,mqseries加载库。
如果库不是从 java 明确加载的,即必须使用依赖库,则必须使用 LD_LIBRARY_PATH
才能在 jvm 中使用该库。