I am trying to access a 3rd party c++ DLL using JNA. I have looked at the JNA documentation available and some blog for understanding JNA.
But now I am stuck with a problem. The DLL which I have has multiple classes in it. And the functions are defined inside the classes. So there is a hierarchy. How can I access the functions then?
For example I have a DLL named: "abc.dll'. In this dll I have class "pqrs" and in that class there is a function called xyz(). I want to access xyz() function.
Until now I am able to load abc.dll successfully as following:
abc abcDLL = (abc) Native.loadLibrary("abc", abc.class);
I have created a interface like this:
public interface abc extends Library {
void xyz(); // this is wrong because "xyz" is not directly "abc.dll" but inside the class "pqrs" which is inside abc.dll
}
And like this there are multiple classes inside the dll. I have searched the web a lot about this. But could not find a solution. I came across to these posts:
Accessing DLL methods with contain mulitple classes using JNA
http://www.javaprogrammingforums.com/java-theory-questions/8865-using-jna-access-export-native-classes.html
But nobody has answered there.
Related
I was given a shared object (*.so file) that I need to reference from my app. I know for a fact that the shared object uses JNI. Now, I have some experience with Android app development, but none with native code. I have looked at a lot of answers here on StackOverflow and on Google in general, but none seem to fit in my question.
Basically, this shared object was for another app, and I have the code for that app, and now I need to implement it in my app. I am lost as to where I should start or what I should do. If anyone can help guide me through this process that would be very nice.
Also, I do not have the source files nor the header files for the shared object. I do know the name of the native method.
If you don't have the Java sources that defined these native methods originally, you can often reverse engineer the necessary native method definitions from the .so file itself. E.g., if the library exports Java_com_example_testjni_MainActivity_stringFromJni, then you must add a Java class
package com.example.thestjni;
class MainActivity {
public native static String stringFromJni();
}
This does not give your the correct parameters or return types for the native methods. Also, you must guess whether the native method should be declared static or not.
To be on the safe side, you will add a static constructor to this class, to make sure the library is loaded:
package com.example.thestjni;
class MainActivity {
static {
System.loadLibrary("thirdparty");
}
public native static String stringFromJni();
}
You are free to rename the 3rd party library to your liking, but not the package and not the class. You don't care if the original Java class declared the native method private, you can safely declare it public in your project.
To find the names of JNI functions exported by prebuilt library libthirdparty.so, you can use the nm tool provided with Android NDK toolchains:
nm -D libthirdparty.so | grep Java_
If you have the Java code for another app that uses it- find the Java code in the other library that calls it. Those functions should be defined with the keyword native. Take that class(es), without renaming or changing the package, and put it in your project. Now you can call those native functions via the Java native function definitions.
Of course without source you can't compile for any other architecture. So hopefully you have the .so files for all the appropriate ones. Remember to load the library if those class(es) don't do it for you.
Is there a way to get Java package and classname from which native library was initialized from JNI_OnLoad? I want to reuse my native library in multiple Java projects and don't know in advance classname and package from where LoadLibrary("mynativelibrary") is called. Then I could use JNI RegisterNatives with dynamic classname.
I've come across the same problem recently. I ended up reusing the class (i.e. copying the code) which loads the native library and handles all callbacks into other projects keeping the original package name. If you make that class generic and use an interface for callbacks then it shouldn't have any dependency on the project and so can be used anywhere. Works well for me.
If you want to load multiple versions of a class, you can do so if they implement a shared interface and are in separate JARs, using a separate class loader for each version.
If you have a JAR that calls native code, you can store the shared library (DLL) for the native code in its JAR by extracting the shared library to a temporary file and then using System.load to load the library from the temporary file.
But if you do both, will it work? What happens if both versions of the JAR call native code, and both contain a different version of the shared library?
Let us assume that both JARs use a different temporary file to store the copy of the shared library. But the two versions of the shared library have native code that call native (C) functions that have identical declarations (but the implementations of those functions are different). Will the JVM/class loader/System.load delegate from the Java code to the correct native code? Or will the JVM complain about name conflicts?
If that scheme does fail, how do I use multiple versions of a class that uses native code?
Examining the Open JDK 7 implementation, it seems that, yes, loading multiple versions of Java classes that use native code will work:
Library Loading
Crucial information is, how does System.load behave? The implementation of that method will be system dependent, but the semantics of the various implementations should be the same.
System.load delegates to the package-private method Runtime.load0.
Runtime.load0 delegates to the package-private static method ClassLoader.loadLibrary.
ClassLoader.loadLibrary delegates to the private static method ClassLoader.loadLibrary0.
ClassLoader.loadLibrary0 creates an object of the package-private inner class ClassLoader.NativeLibrary and delegates to its load method.
ClassLoader.NativeLibrary.load is a native method, which delegates to the function JVM_LoadLibrary.
JVM_LoadLibrary delegates to os::dll_load.
os::dll_load is system dependent.
The Linux variant of os::dll_load delegates to the dlopen system call, giving the RTLD_LAZY option.
The Linux variant of the POSIX dlopen system call has RTLD_LOCAL behaviour by default, so the shared library is loaded with RTLD_LOCAL semantics.
RTLD_LOCAL semantics are that the symbols in the loaded library are not made available for (automatic) symbol resolution of subsequently loaded libraries. That is, the symbols do not enter the global namespace, and different libraries may define the same symbols without generating conflicts. The shared libraries could even have identical content without problems.
Hence it does not matter if different shared libraries, loaded by different class loaders, define the same symbols (have the same names of extern functions for native methods): the JRE and JVM together avoid name clashes.
Native Function Lookup
That ensures that the multiple versions of the shared libraries do not generate name conflicts. But how does OpenJDK ensure that the correct JNI code is used for the native method calls?
The procedure followed by the JVM to call a native method is rather lengthy, but it is all contained within one function, SharedRuntime::generate_native_wrapper. Ultimately, however, that needs to know the address of the JNI function to be called.
That wrapper function makes use of a methodHandle C++ object, getting the address of the JNI function from either the methodHandle::critical_native_function() or methodHandle::native_function(), as appropriate.
The address of the JNI function is recorded in the methodHandle by a call to methodHandle::set_native_function from NativeLookup::lookup.
NativeLookup::lookup delegates, indirectly, to NativeLookup::lookup_style
NativeLookup::lookup_style delegates to the Java package-private static method ClassLoader.findNative.
ClassLoader.findNative iterates through the list (ClassLoader.nativeLibraries) of ClassLoader.NativeLibrary objects set up by ClassLoader.loadLibrary0, in the order that the libraries were loaded. For each library, it delegates to NativeLibrary.find to try to find the native method of interest. Although this list of objects is not public, the JNI specification requires that the JVM "maintains a list of loaded native libraries for each class loader", so all implementations must have something similar to this list.
NativeLibrary.find is a native method. It simply delegates to JVM_FindLibraryEntry.
JVM_FindLibraryEntry delegates to the system dependent method os::dll_lookup.
The Linux implementation of os::dll_lookup delegates to the dlsym system call to lookup the address of the function in the shared library.
Because each class-loader maintains its own list of loaded libraries, it is guaranteed that the JNI code called for a native method will be the correct version, even if a different class loader loads a different version of the shared library.
If you try to load the same library in different class loaders you will get an UnsatisfiedLinkError with the message "Native Library: ... already loaded in another class loader". This might have something to do with the VM calling the library's unload method when the class loader is garbage collected (https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/design.html#compiling_loading_and_linking_native_methods).
But if you - as you say - "use a different temporary file to store the copy of the shared library" the two are effectively different libraries regardless of the files' contents (might be binary identical, doesn't matter). So there isn't a problem.
I saw a lot of examples on how to use primitive java classes in .NET, but how I can use my own Jar in .NET? Until now I could do this by reflection, but because I have a method with parameters File[] and String[] and jni4net doesn't have a definition for class of this (i.e. File[].class), I cannot invoke them.
I couldn't find a step by step tutorial on how I can do this. I tried with generateProxies.cmd, but I still cannot make it work.
Thanks a lot
There is DLL file called as myAPI.dll. It contains classes that I'd like to use in my JAVA code. How to import this DLL file into my Java project in Eclipse? It should be possible to run the code based on something like this:
import myAPI;
public class MyClass {
//...
}
}
I do not know which language is used for your code snippet but it is definitely not java. Java does not have keywords like using and namespace.
Generally to call native code from java you have to use good old JNI or newer JNA.
Please follow the following links to get started with these technologies.
http://java.sun.com/docs/books/jni/html/start.html
http://www.javaworld.com/community/node/1767
The code snippet you have shown is C#, not Java. Now namespace lets you group logically related things. For e.g. all order processing related classes can be put under single namespace. It is also used as a mechanism to avoid/resolve name conflicts. It also defines the visibility scope of your class. Read this lesson for more details.