Я делаю программное обеспечение (для Android) для считывания значений счетчиков с датчиков. Ожидается, что программное обеспечение будет получать обновления очень часто, чтобы поддерживать большее количество датчиков. Функциональность для считывания данных счетчиков для этих датчиков реализована в собственных библиотеках, загружаемых приложением в приложении.
У меня есть список общих объектов и функция ввода, которая должна быть вызвана (возвращаемое значение сохраняется):
libprintf.so,hookPrintf
libharx.so,hookHarx
Каждая библиотека загружается во время выполнения: System.loadLibrary("printf");
Подпись каждой функции будет выглядеть так:
public native int hookPrintf();
public native int hookHarx();
Проблема в том, что я не знаю заранее (во время компиляции), какие общие объекты должны быть загружены, и поэтому я не могу добавить эти подписи в источник java.
Я попытался использовать Reflection для динамического вызова методов следующим образом:
Method entryMethod = Expat.class.getMethod(hookMethod);
Object test = entryMethod.invoke(this);
System.out.writeln(test.toString());
Однако, если подпись отсутствует, это будет по-прежнему терпеть неудачу с исключением NoSuchMethodException. Есть ли другой способ, чтобы иметь возможность называть собственные методы, не требуя, чтобы они определялись заранее?
Изменение: используя функцию RegisterNatives, я могу динамически регистрировать свои функции из общего объекта, но для этого все еще требуется, чтобы подпись метода определялась в классе. Что делает метод registerNatives()?
Вероятно, вы можете иметь класс Java только с двумя собственными методами и полагаться на RegisterNatives и UnregisterNatives и переключать загруженные собственные реализации во время выполнения. При этом я предпочел бы использовать собственную библиотеку-оболочку с собственными методами
private static native void hook(String libName, String hookName);
Эта оболочка будет использовать dlopen() или LoadLibraryEx(), а также, при необходимости, выгружать внешние библиотеки.
В некоторых JVM вы можете динамически создавать новые классы, но это довольно сложно.
У вас есть фундаментальная проблема дизайна. Я бы предложил вернуться и создать JNI-библиотеку, которая реализует один метод, такой как public native int createHook() или что-то подобное. Затем сделайте выбор в своем родном коде на основе некоторого условного. Если вам все еще нужно/нужно загружать библиотеки во время выполнения, создайте библиотеки non-jni для libprintf.so и libharx.so и используйте либо dlopen для динамической загрузки библиотеки, либо слабо свяжите библиотеки с библиотекой jni.
native
.