Existe uma diferença entre definir o argumento da JVM
-Djava.library.path=/path
na boot da JVM e definindo a variável de ambiente do Linux
export LD_LIBRARY_PATH=/path
antes de a JVM ser iniciada?
Quais são as vantagens / desvantagens das duas abordagens?
A primeira forma
-Djava.library.path=/path
será manipulado no nível do bytecode java, o System.loadLibrary
chamará Runtime.loadLibary
, em seguida, chamará java/lang/ClassLoader.loadLibrary
. Na chamada de function ClassLoader.loadLibrary
, a propriedade do sistema java.library.path
será verificada para obter o caminho completo da biblioteca e passar esse caminho completo para o código nativo para chamar o api dlopen/dlsym
sistema dlopen/dlsym
, eventualmente, tornar a biblioteca carregada. Você pode procurar a fonte do repository OpenJDK . O trecho de código a seguir é o segmento que copio do link.
A vantagem dessa forma é que você obterá erro ou aviso ou exceção no código Java, se houver algum problema com o caminho da sua biblioteca.
// 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); } // ....
A segunda forma
export LD_LIBRARY_PATH=/path
será tratado em nativo, de acordo com o documento do 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.)
Dessa maneira, se houver algum problema com o caminho da sua biblioteca e o sistema não puder carregar sua biblioteca, o sistema não dará muita pista do que acontecerá e falhará silenciosamente (eu acho). Depende se deve ou não implementar LD_LIBRARY_PATH
, o Android não usou LD_LIBRARY_PATH
para determinar a localização da biblioteca, você pode ver a implementação do Android a partir daqui .
Java pode carregar explicitamente as bibliotecas listadas com -Djava.library.path=...
como descrito por alijandro.
Por exemplo, se mq series for usado no modo de ligações, o caminho para as bibliotecas necessárias pode ser especificado com -Djava.library.path=/opt/mq/java/lib
e o mqseries carrega as bibliotecas.
Se uma biblioteca não for explicitamente carregada de java, ou seja, uma biblioteca dependente precisa ser usada, então LD_LIBRARY_PATH
deve ser usado para ter essa biblioteca disponível no jvm.