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.
Related
Some of my Kotlin classes are implemented by a native library (Rust using jni). These classes are used in most of the activies and by one sync service (a second service may come later).
What is the recommended solution to load this library and handle loading errors (for example sending a bug report if loading fails)?
Basic examples loads a library in the MainActivity.onCreate. Or often I see a static block inside the MainActivity class.
Another method may be loading the library in a derived class from Application. But I'm not sure if there is only one Application instance for all activities and services or if one `` Application``` instance is created for each service and another one for all activities.
So my question is: where to put System.loadLibrary()?
Yes, the Application is a singleton for the whole Android app. But you should not worry, LoadLibrary() does nothing if the library had been loaded before. So, the best practice is to add LoadLibrary in static blocks of all classes that depend on this library.
Consider using ReLinker library that provides logging and also workarounds for some widespread problems with loading native libraries.
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.
I need a way to load library inside a jar file without extracting it. Is there a way I can use a method like getClass().getResourceAsStream("xxx")
structure will be as follows:
myjar.jar
- lib/
- <somelib>.<libext>
- <package>
- Foo.class
Where the Foo.class will be the class that loads and connect to the native library and method should also work if the lib folder was inside the <package>
No, there is no way to load library from inside of a jar file without extracting it first, you need to extract the library at least into tmp folder in order to be able to load it using eg:
System.load("path/to/libAbc.so")
It is not currently possible in java to load the library from memory or zip file. The method that loads the library is native void ClassLoader.NativeLibrary.load(String name), also the name of the library is used internally by the java.lang.ClassLoader to keep the track of loaded libraries, so currently you can't use anything different than a real file to be loaded as native library because it wouldn't fit the current mechanism.
Since the loading of the native library is done with the help of native code, the answer depends if there is a way to load the native library in a C code: dlopen from memory?
Theoretically it can be done, but bacause it is platform specific and have many aspects that needs to be considered and resolved it isn't implemented in Java and it isn't a standard and/or easy thing in C either.
Currently in java, there is no way to do it, this could change if someone will create such a native library that will do that, but for now I don't know any such library.
Also sci-java native lib loader handles this (although it extracts it behind the scenes).
You may want to try it: https://mvnrepository.com/artifact/org.scijava/native-lib-loader
You can't do it without putting it somewhere (at least some temporary location).
You can take a look here:
https://github.com/mkowsiak/jnicookbook/tree/master/recipes/recipeNo031
This recipe gives you a template that will take your native library from jar, extract it, and load inside your Java code.
Have fun with JNI!
I have a C++ application that uses plugins (it dynamically loads certain shared lib files). I'm having some trouble understanding what I need to do to call into dynamically loaded native code from Java.
Do I have to use System.loadLibrary/System.load to 'preload' native shared objects ("plugins") to be able to call into that native code? Or would I be okay only calling RegisterNatives from within the plugin after loading it in my native code? I've already called System.loadLibrary for my main native application lib -- its the subsequent plugins the native lib loads that this question is for.
And if I can get away with only calling RegisterNatives what would happen if I suddenly decide to unload a plugin and the JVM tries calling a native method that was inside it?
At least Android VM requires that all native methods must be "registered" when the class is instantiated. That's why System.load() is usually called in static constructor, and not later.
The two ways to resolve native methods are through RegisterNatives() in JNI_OnLoad() or though name matching (C exported functions names as reported by javah).
You can look for function pointers for RegisterNatives() in all loaded modules, or load more modules and get pointers from them. RegisterNatives() may be called at any time, and if you really want to unload some plugins you can make use of UnregisterNatives().
The latter was introduced to support the following flow (pseudo-code follows):
SwitchPlugin() {
UnregisterNatives();
unloadPlugin(oldHandle);
newHandle = loadPlugin(newPluginName);
RegisterNatives();
}
Your app will probably crash miserably if it tries to use a native method that is implemented in an unloaded plugin or after it is unregistered with UnregisterNatives().
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.