Cedric VB
Cedric VB

Reputation: 222

Calling native method dynamically in Java

I'm making software (for Android) to read out meter values from sensors. The software is expected to receive updates very often in order to support more sensors. The functionality to read out the meter data voor these sensors is implemented in native libraries that are downloaded on runtime by the app.

I've got a list of shared objects and an entry function that should be called (the return value is saved):

libprintf.so,hookPrintf
libharx.so,hookHarx

Each library is loaded at runtime: System.loadLibrary("printf");

The signature of each function would look like this:

public native int hookPrintf();
public native int hookHarx();

The problem is that I don't know beforehand (at compile time) which shared objects will have to be loaded, and thus I can not add these signatures in the java source.

I tried using Reflection to call the methods dynamically as follows:

Method entryMethod = Expat.class.getMethod(hookMethod);
Object test = entryMethod.invoke(this);
System.out.writeln(test.toString());

However, if the signature is not present, this will still fail with a NoSuchMethodException. Is there another way to be able to call native methods without needing to have them defined beforehand?

Edit: Using the RegisterNatives function, I can register my functions dynamically from the shared object, but that still requires the method signature to be defined in the class. What does the registerNatives() method do?

Upvotes: 1

Views: 2307

Answers (2)

Alex Cohn
Alex Cohn

Reputation: 57183

You probably can have a Java class with only two native methods, and rely on RegisterNatives and UnregisterNatives and switch the loaded native implementations at runtime. With that, I would rather use a native wrapper library with native methods

private static native void hook(String libName, String hookName);

This wrapper will use dlopen() or LoadLibraryEx() and also unload the external libraries when necessary.

In some JVMs you can dynamically create new classes, but that is quite tricky.

Upvotes: 3

Alex Barker
Alex Barker

Reputation: 4400

You have a fundamental design issue. I would suggesting going back and create a JNI library that implements a single method like public native int createHook() or something equivalent. Then make the choice in your native code based on some conditional. If you still want/need to load the libraries at runtime, create non-jni libs for libprintf.so and libharx.so and use either dlopen to dynamically load the library or weakly link the libraries to the jni library.

Upvotes: 1

Related Questions