In a Java program i am writing i make a jni call to a dll and load the library on startup as follows
static
{
System.loadLibrary("LdapAuthenticator2");
}
I then implemented another class that loads the same library and am getting an error saying that the library is already loaded, is there any way to check if the library is already running?
Thanks,
-Pete
Check my answer to this question
How do I get a list of JNI libraries which are loaded?
The solution works, unfortunately the poster of the question seems to have problems with a non SUN compatible JVM or a too restrictive SecurityManager.
Link to the sample POC source code.
List loaded JNI libraries java sourcecode
What kind of an error? If it's an exception, can you just catch it?
Another approach would be to make exactly one class responsible for loading the library. You could make loading the library part of the class's static initializer, and then loading the class == loading the library.
EDIT: the javadocs for Runtime.loadLibrary() (which System.loadLibrary calls) even suggests the static initializer approach:
If native methods are to be used in the implementation of a class, a
standard strategy is to put the native
code in a library file (call it
LibFile) and then to put a static
initializer:
static { System.loadLibrary("LibFile"); }
within the class declaration. When the class is loaded and initialized,
the necessary native code
implementation for the native methods
will then be loaded as well.
The javadocs also say:
If this method is called more than once with the same library name, the second and subsequent calls are ignored.
which makes me even more curious about the error you're getting.
Related
I faced with the problem:
Native Library Ltkrnx.dll already loaded in another classloader
during redeploy application(tomcat 8 server).
I also added check, but it's doesn't help me.
private void loadLibrary(LTLibrary library) {
if (!Platform.isLibraryLoaded(library)) {
Platform.loadLibrary(library);
}
}
Caused by: leadtools.RasterException: Native Library C:\LEADTOOLS 20\Bin\CDLL\x64\Ltkrnx.dll already loaded in another classloader
Are you using LEADTOOLS in 2 different web applications? If yes, the following answer might help you solve the problem:
java.lang.UnsatisfiedLinkError: Native Library XXX.so already loaded in another classloader
Since that question is about OpenCV, not LEADTOOLS, I will quote the relevant parts here (very slightly edited):
Now there's the restriction that a native library can only be loaded
in one class loader. Web applications use their own class loader so if
one web application has loaded a native library, another web
application cannot do the same. Therefore code loading native
libraries cannot be put in a webapp directory but must be put in the
container's (Tomcat) shared directory. When you have a class written
with the usual pattern above (loadLibrary in static initializer of
using class) it's enough to put the jar containing the class in the
shared directory. With .. the loadLibrary call in the web application
code however, the native library will still be loaded in the "wrong"
class loader and you will get the UnsatisfiedLinkError.
To make the "right" class loader load the native library you could
create a tiny class with a single static method doing only the
loadLibrary. Put this class in an extra jar and put this jar in the
shared Tomcat directory. Then in the web applications replace the call
to System.loadLibrary with a call to your new static method. This way
the class loaders for the .. native library will match and the native
methods can be initialized.
If your situation is different, or the suggestion there doesn’t help you, send the following information to support#leadtools.com and our support team will work with you to isolate the problem:
The details of this question (exception you’re getting, version 20 of LEADTOOLS, 64-bit, Tomcat 8)
Your LEADTOOLS product serial number (don’t post it here!). If you’re still evaluating and don’t have a serial number, just mention that.
What you’ve tried so far to solve the problem and what results that gave you (for example, the answer mentioned above).
Other details about your OS, IDE or programming environment in general.
Lets say that a lot of functionality are using methods from this class test.MyClass, but it's very slow and I'd like to code in JNI in hopes of improving the timing...
Is there a way to replace test.MyClass so that the library does not need to be changed, but the codes in the library will use the new test.MyClass with native implementations for certain methods from now on? It's the classic "PC is fine but the timing for Android is crap" problem.
Just create your test.MyClass in the same package/hierarchical structure as the one in the package you want to override. The classloader should load your implementation first and if it tries to load the one from other library the load will fail, because there can be only one loaded instance in the classpath.
I'm using JNI in my app. In Java classes which need native things I load the native library like so:
static
{
System.loadLibrary("nativeegl");
}
To be honest I don't know what the static thing does exactly, but I guess this is to make sure that the nativeegl library is loaded before anything else. Don't remember where I got this pattern from.
Now if this is a View subclass, and I'm using the graphical editor in Android Studio, the editor can't load the view subclass because of this exception:
java.lang.UnsatisfiedLinkError: no nativeegl in java.library.path
Since View.isInEditMode() is an instance method, I can't use it within the static{} block.
Is there an alternative? Maybe I can load the library differently?
Now that I think about it, one possible workaround is to split your View code into two classes: the actual View, and a separate standalone class that contains your JNI code, including the static block. For the purposes of the rest of this answer, I'll call these FooView and BarWrapper, respectively.
Then, only reference BarWrapper from code in FooView that is inside an if (isInEditMode()) block.
This may prevent BarWrapper from being loaded by the Java/pseudoAndroid environment used by the GUI builder, and therefore not trigger the attempt to load your native library. Leastways, the Dalvik classloading rules would cause BarWrapper to be ignored, as classes only get loaded when they are first used, and in your case you would be skipping over all code that uses BarWrapper. Hopefully, the GUI builder code adheres to how Dalvik handles it, though that's far from assured, since it's running on a Java VM, not an Android VM (Dalvik or ART).
It may make your code a bit more clunky, as you have to split out your logic between two classes instead of just one. But, it may be worth an experiment.
for bytecode instrumentation in java, there is the asm framework and the bcel and javaassist libraries.
However I need to do instrumentation in native code, since some java classes are already loaded by the time the javaagent runs, eg java.lang.Thread, java.lang.Class, etc
is there any library for instrumenting java classes in native code?
Edit:
Seems there is a bit of confusion.
What I want is:
Create a native java agent, which uses JVMTI apis to change the bytecode of a class while its being loaded, using the OnClassLoad event hook.
I encountered this problem during my doctoral research. The answer that worked best for me was to perform the byte-code modification in a separate JVM using a java library (I used ASM).
I used the JVMTI class load hook to capture the class file and transmit it to the separate JVM using a tcp connection. Once the class had been modified within the separate JVM I returned it to the JVMTI Agent, which copies it into VM memory and returns a pointer to the modified class file to the JVM.
I found that it was too difficult to weave classes within the same JVM as was being profiled as the system class files I wanted to modify (java.lang.Object, for example) had to be loaded before any class files I needed to perform weaving. I hunted for c/c++ bytecode libraries without much success, before settling on the separate JVM approach I finally used.
You can parameterize the JVMTI agent with the hostname/port of the weaver JVM, or you could use some form of discovery, depending on your requirements.
The JIT will turn byte code into native code. If you want to produce native code, you need to let the JIT do it or write native code which is called via JNI.
Perhaps what you are trying to achieve can be done simpler another way.
Create a native java agent, which uses JVMTI apis to change the bytecode of a class while its being loaded, using the OnClassLoad event hook.
Though you don't need to do what you want. Why make the solution more complicated (and less likely to work) than it needs to be?
You cannot change the byte code of a class once it has been loaded. You can either make sure your instrumentation runs before it is loaded, or you can create a new ClassLoader, and re-load the classes inside of it by not asking the parent class. You can't use those classes with code loaded outside of the ClassLoader though, as that code will refer to the earlier loaded, non-altered class.
I want to inject my Java class into an existing Java application, on Windows.
I found an article describing a method using CreateRemoteThread - java-code-injection-via-winapis
But it's not clear if the injected class can 'connect' with the existing classes and call them.
Does anybody know if this is possible? Are there functions in the JNI which can be used to search and get a reference to already running classes?
i'm sure there are other complicated ways to do what you want to do (e.g. using the java instrumentation apis). however, there is probably a much easier way.
find the class which is the main class for the application
decompile the class into java code.
add a simple hook to invoke your custom code (or otherwise modify this class to suit your needs)
recompile the modified class and replace the class file in the relevant jar
run your modified application!