Skip to Main Content

Java HotSpot Virtual Machine

Announcement

For appeals, questions and feedback about Oracle Forums, please email oracle-forums-moderators_us@oracle.com. Technical questions should be asked in the appropriate category. Thank you!

Interested in getting your voice heard by members of the Developer Marketing team at Oracle? Check out this post for AppDev or this post for AI focus group information.

loadLibrary doesn't use java.library.path set at runtime

843829Jun 9 2001 — edited Nov 9 2005
I'm trying to set the property java.library.path at runtime so I don't have to drop my .dll in the regular system path for a System.loadLibrary to work. This is the sequence I use in a static initilizer:

System.setProperty("java.library.path", "C:\\");
System.loadLibrary("DialButton");

When I put the file DialButton.dll in C:\ I get an java.lang.UnsatisfiedLinkError, but when I put it in D:\WINNT it works fine. I would expect it to do the opposite because presumably I blew away the real java.library.path when I ran setProperty and it shouldn't know to check D:\WINNT.

I'm trying to keep my application install clean and use a directory structure that maintains all of the required files without cluttering system directories. I also want to dynamically load JNI libraries for a distributed application after copying them to the local machine.

Thanks in advance,
Ryan

Comments

843829
Try printing java.library.path System property before you override it, see what you have there.
The best way, in my opinion is to ADD to the library path. Maybe the JVM doesn't find the libraries it needs so it resorts to the default? Doesn't make sense!
Also try running with
java -Djava.library.path=...;<regular library path>

Hope this helps,
Ami
843829
Or you could just use System.load(..) and specify the absolute path to the library.
843829
I gave up on trying to specify the path for System.loadLibrary. When I just use System.load and specify the complete pathname, it works great.

Thanks,
Ryan
843829
Hi All,

There are few things I discovered regarding setting
the loading of .dll on the Windows platform:

1. Set your path to %PATH% instead of %LIB% to
get it included in the search path for the DLL's.

Or

2. Do the following:
// Check some System properties
String strLibPath = System.getProperty("java.library.path");
System.out.println("JNIMgr: The Lib Path set == " + strLibPath);

// Set the LibPath
StringBuffer strLibPathBuffer = new StringBuffer("<your-drive-name>:\\<your-dll-path>;");
strLibPathBuffer.append(strLibPath);
System.setProperty("java.library.path", strLibPathBuffer.toString());

It works for me on Windows2000 and using JDK1.3!

Sincerely,

<-
Bazil Farid
Sun Microsystems Inc.


843829
Java LoadLibrary probably calls win32 LoadLibrary, and this function searches the dll in th following order:
First, in the current directory of the process.
Second, in the path directories.

java.library.path probably tells java where to look for class libraries, not DLLs.

You should either put your dll in the current directory of your running JVM, or put it in some directory of your path.

Of course Load java function with full path works, but it is not easily configurable neither portable!
843829
Hi Bazil Farid,

The method System.setProperty() doesn't work the way it seems.
In fact if you use it, the parameter you changed will be setted as you wanted to (you can print it to check it), but the JVM won't use the new property you defined (-> it won't be reloaded).
ie, you didn't really change your library path, and your dll won't be loaded if it is not in a directory of the PATH variable (if you use Windows).
843829
so what is the answer? Is it possible to set your library path dynamically?
so what is the answer? Is it possible to set your library path dynamically?
No, not in a way that will change the default class loading behaviour of the JVM.
843829
Correct, you cannot change java.class.path dynamically either.
843829
Iam trying to call a dll but couldn't get required output.The class files is able to reach dll but there was some error in finding method.Exact Exception is:
Exception in thread "main" java.lang.UnsatisfiedLinkError: ConvertChr
at test.ConvertChr(Native Method)
at test.main(test.java:16)

My java code is :

public native String ConvertChr(long ascvalue);

static
{
System.loadLibrary("SimpleFunctions");
}

public static void main(String args[])
{
test t = new test();
System.out.println(t.ConvertChr(122));
}
}

/*
dll methods

Public Function ConvertAsc(vString As String) As Integer
Dim i As Long
Dim newString As String
newString = ""
newString = Asc(vString)
ConvertAsc = CInt(newString)
End Function

Public Function ConvertChr(vLong As Long) As String
Dim i As Long
Dim newString As String
newString = ""
newString = Chr(vLong)
ConvertChr = newString
End Function

*/

Could anyone help me in finding solution.Iam using VB generated DLL.

Thanks

Somal
843829
1. You are unwise to attach new questions to old forum postings. People with answers frequently ignore topics that show answers appended. If you have a question, post a new topic.

2. There have been other questions posted about VB dll use. You should be looking for them and using the answers.

3. A VB Dll - or any other "normal" dll - is not going to be callable directly from java. Java places special requirements on the calling sequence of the native code. What you have to do is

a) define a "nice" java native method - takes and returns the kinds of java objects you want.

b) Run javah on the object. This will generate the required function signatures for a native dll.

c) Implement the native DLL - in C. In your case, you will probably make this a "wrapper" DLL, which calls your VB dll. (I assume that you know how to do C-to-VB calls.)
843829
In the bug parade I've heard excuses from Sun programmers that this is a read-only property and isn't supposed to be changed. It probably took them longer to write the reply to the bug than it would have to fix the code.

I looked at the source code for the ClassLoader and for the source release of the JDK 1.3.1 and here's the code I found in the ClassLoader.loadLibrary() method:
        if (sys_paths == null) {
                usr_paths = initializePath("java.library.path");
                sys_paths = initializePath("sun.boot.library.path");
        }
It seems it parses and caches the system and user library paths on startup and then never bothers to check them to see if they've changed ever again. I think it would be pretty simple to rewrite that code block by moving one line of code down two lines as this:
        if (sys_paths == null) {
                sys_paths = initializePath("sun.boot.library.path");
        }
        usr_paths = initializePath("java.library.path");
I mean, it's not as if loadLibrary is really performance intensive or even critical enough to bother caching at all!

This one code change could fix a lot of headaches.

The particular headache I'm working on is that there doesn't seem to be any support in the Servlet 2.2 or 2.3 specification for JNI files. I'd really love to be able to use a directory like WEB-INF\jni to store libraries that need to be distributed with my web application. I tried to dynamically change java.library.path to include WEB-INF\jni, but alas I ran into the same problem you did, it doesn't work.

Is is possible for this to be fixed, ever? I think it would take longer to say no and make up a reason why not then it would to actually make the fix... seems a good enough arguement to do it to me.

And alternately, can we come up with a standard place to put JNI stuff for web applications in the next Servlet standards?

Thanks in advance!

-J.C.
jhamlin@dynamic-info.com
843829
Take a look at this Bug Report

http://search.java.sun.com/ClickThru?qt=%2B+%2Bloadlibrary&url=http%3A%2F%2Fdeveloper.java.sun.com%2Fdeveloper%2FbugParade%2Fbugs%2F4280189.html&pathInfo=%2Fsearch%2Fjava%2Findex.jsp&hitNum=4&col=javabugs
843829
Well, I found an interesting way to make it rather dynamic, if just using a workaround. It's not pure dynamic, but it works.

The only path we have really have control is the classpath. So, technically, you could put your library path as one of the class path. Then grab the class path property and enumerate every path. Find the path that end in the one your interested to. You simply end it by pre-apending the path to the library you want to load, and use, as everyone else suggested, the System.load(...) command.

It's not pure dynamic, but it should work well. It's what I'm using in my app.
843829
Of course Load java function with full path works, but
it is not easily configurable neither portable!
Well, the simplest workaround for the configurability/portability issue is to construct a File using the relative path (which you can even specify in a properties file, if you wish), and then use File.getAbsolutePath().

I would think this is probably the simplest/best workaround until they decide to make java.library.path writable (if that ever happens)...
843829
Hi!

This is a rather old thread but as nothing has changed since the first post (the ClassLoader still contains the caching) I'll post my solution here for the ones who find this page via google :).

If you can't use System.load instead of loadLibrary (because the JNI lib isn't loaded by your code) then you can still fall back to reflection hacking. As it can be seen from the source code of ClassLoader (as qouted in an earlier response) the result of parsing the java.library.path variable is cached by the ClassLoader:
        if (sys_paths == null) {
	    usr_paths = initializePath("java.library.path");
	    sys_paths = initializePath("sun.boot.library.path");
        }
What we can do is that we set sys_paths to null using reflection:
Class loaderClass = ClassLoader.class;
Field userPaths = loaderClass.getDeclaredField( "sys_paths" );
userPaths.setAccessible( true );
userPaths.set( null, null );
Calling System.loadLibrary know will use the new value in the java.library.path property (which you can set any time before the loadLibrary call). Here is a simple test application that loads a jni lib from ../lib
import java.lang.reflect.Field;

public class LoadLibTest {
    public static void main( String args[] ) throws Exception {
         System.setProperty( "java.library.path", "../lib" );
          String libName = "nameOfYourLib"; // Set this to the name of the lib
         
         Class loaderClass = ClassLoader.class;
         
         Field userPaths = loaderClass.getDeclaredField( "sys_paths" );
         userPaths.setAccessible( true );
         userPaths.set( null, null );
         System.loadLibrary(  libName  );
    }
}
1 - 16
Locked Post
New comments cannot be posted to this locked post.

Post Details

Locked on Dec 7 2005
Added on Jun 9 2001
16 comments
4,760 views