In a subset of the Java ecosystem related mainly to JNI (without which there is no way to go if you have to integrate with some kind of legacy or just rare and specific code written in C or some other language), there is such a thing as java. library.path. In short, this is in some way analogous to the classpath, not only for Java classes and * .jar files, but for native libraries - a system property that tells the JVM where to find these native libraries (.dll in Windows or .so under Unix).
This property is set once, before running the JVM, through the global system properties, or as the -Dname = value key for the JVM, and after that it becomes read-only. More precisely, it can be changed, but it will have no effect on the program’s work, since after you update this property, the JVM will not reread it and will not use the new value.
Under the cut, it’s about how to change this property in runtime, and a little about how the loading of native libraries in Java actually works.
')
However, the ability to change java.library.path on the fly would be very useful - then you would not have to generate, rewrite and rewrite scripts to run JBoss many times, for example, to reflect all the necessary paths to the start of the appserver.
And such an opportunity, to change these ways in which the JVM is looking for native libraries, is actually there. Specific techniques are shown here -
blog.cedarsoft.com/2010/11/setting-java-library-path-programmatically and here again -
nicklothian.com/blog/2008/11/19/modify-javalibrarypath-at-runtime .
And here I will describe the download mechanism itself, and why what is described in the links works. Usually, native libraries are loaded through a static initializer:
static {
try {
System.loadLibrary(«dp-integ»);
}
}
* This source code was highlighted with Source Code Highlighter .
Which looks like this:
public static void loadLibrary( String libname) {
Runtime.getRuntime().loadLibrary0(getCallerClass(), libname);
}
* This source code was highlighted with Source Code Highlighter .
And further in the class Runtime:
synchronized void loadLibrary0(Class fromClass, String libname) {
// ,
SecurityManager security = System.getSecurityManager();
if (security != null ) {
security.checkLink(libname);
}
if (libname.indexOf(( int ) File .separatorChar) != -1) {
throw new UnsatisfiedLinkError( "Directory separator" +
"should not appear in library name: " + libname);
}
ClassLoader.loadLibrary(fromClass, libname, false );
}
* This source code was highlighted with Source Code Highlighter .
Those. as a result, native libraries are loaded, as well as regular classes, through ClassLoader. The ClassLoader class has two properties in which initialized search paths are cached.
// The paths searched for libraries
static private String usr_paths[];
static private String sys_paths[];
* This source code was highlighted with Source Code Highlighter .
The code for the ClassLoader.loadLibrary method (fromClass, libname, false), is quite long, and cluttered with numerous checks, in abbreviated form it looks like this.
// 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" );
// , ,
// boot classpath.
sys_paths = initializePath( "sun.boot.library.path" );
}
// , ,
// , -
// Oops, it failed
throw new UnsatisfiedLinkError( "no " + name + " in java.library.path" );
}
* This source code was highlighted with Source Code Highlighter .
Thus, now the mechanism of loading the native library has become more understandable.
You can either set the sys_paths property of the classifier to null, or simply change the sys_paths / usr_paths properties by adding the necessary paths to your native libraries to them.