1

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?

Community
  • 1
  • 1
Cedric VB
  • 222
  • 1
  • 7

2 Answers2

3

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.

Alex Cohn
  • 56,089
  • 9
  • 113
  • 307
  • Thanks for the UnregisterNatives suggestion by switching the implementations. I'll be going with that. I do believe that your method signature should include the `native` keyword. – Cedric VB Jun 30 '14 at 11:32
  • Thanks, **native** _was_ missing – Alex Cohn Jun 30 '14 at 18:31
1

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.

Alex Barker
  • 4,316
  • 4
  • 28
  • 47
  • I updated the question with my specific use case. That is definitely a possibility, I guess I just hoped it would be easier and Java would pick up on functions that are registered through JNI. Right now I'm dealing with this by creating a stub file which contains hookLib1() until hookLib1000() to support updates for the year to come, which is less than ideal. – Cedric VB Jun 26 '14 at 19:31