I wrote a C++ dll that returns the available space on the hard drive. I have a Java Agent that loads this dll and runs successfully until it runs the second time and get the error “… already loaded in another classloader”. I tried to place the loadLibrary statement in it’s own try block so it would flow through but than it can’t find the function. It works great the first time it is loaded. What can I do to alleviate the error on the consecutive runs. I have checked this forum and have seen nothing to address it.Thanks
Subject: Java Agent and JNI
Hi Joey,
put your class that loads the external library on the system classpath (JavaUserClasses for example or the ext/lib directory). When you load the (dll) library from the agent, it will work the first time but it will barf the next since it has not released its resources since the first time.
Kind regards
Daniel
Subject: RE: Java Agent and JNI
Hi Daniel,
Thanks for the reply but I am not sure I understand. I have 3 class files that I have imported into an agent. You are saying that I need to take the class that loads the library and copy it to the ext/lib directory. I don’t want it to fail the next time it runs. I am not sure how this will help. I have placed it in a static{} in the main class but it still tries to load the second time. I will add the class and try. This adds some complexity as when ever I update the agent I will have to also copy the main class each time.
Subject: RE: Java Agent and JNI
A while ago I wrote a blog post about the same problem. Daniels suggestion to put class libraries to disk is probably the only solution. You must restart Notes after you put the files to the disk.Andrei's Blog about Lotus Domino and other things: Solution for Java error "native library c:\test.dll already loaded in another classloader while loading driver MyDriver"
Subject: RE: Java Agent and JNI
Thanks Andrei for your response. I read your article. I have 3 class files I have imported into an agent. Should I have added them to a JAR file and used that instead and then added that to the classpath? What will happen when I have to alter this agent? Do I have to also replace the JAR file in the classpath and restart the server? Why does the static{System.loadLibrary(“xxx”)} not work?
Subject: Java Agent, JNI & the ClassLoader
Thank you Daniel and Andrei for your post. Here’s some additional detail …
The Symptom:
Create a Java agent.
The Java references a custom JNI.
Java that calls System.load(“jni.dll”) lives in the agent or a jar loaded by the agent.
The agent runs great the first time, but generates the following error on subsequent run attempts …
java.lang.UnsatisfiedLinkError: “jni.dll” (Library is already loaded in another ClassLoader)
The Problem:
The ClassLoader used by the agent is a one-time instance. The next time the agent executes, it gets a new ClassLoader. So the error “already loaded in another ClassLoader” is indeed the problem. The jni.dll is already loaded. The JNI methods cannot be located without a fresh call to System.load(), but that call fails because the original instance is not making the current call.
The Solution:
Let the JVM load (some of) the classes. Drop a jar required by your Java agent into jvm\lib\ext. The jar includes the classes referenced by the agent Java. One of those classes makes the System.load() call. Now it works for every run of the agent, not just the first run. That’s because the ClassLoader instance used was create at JVM start-up and still exists. Notice that if the jar is deposited into jvm\lib\ext while N/D is running, then N/D must be restarted in order for that jar to be recognized at run time.
The DCT Solution:
For DCT we want as little code as possible sitting in jvm\lib\ext to avoid its misuse. The DCT jar dropped into jvm\lib\ext only contains a thin wrapper layer and a DCT specific URLClassLoader. The bulk of the DCT code sits in a private directory defined at run-time, which the URLClassLoader knows how to find. The wrapper makes the call to System.load(jni.dll).
When DCT.NSF is opened, all files are automatically deployed to disk, if necessary. If the jvm\lib\ext jar had not previously exist, the user is instructed to restart Notes before attempting to execute a scan (i.e. the agent requiring that jar).