2013-12-13 4 views
2

У меня есть оператор журнала печати в JNI_OnLoad, но я обнаружил, что он не вызывается. Вот мой метод JNI_OnLoad.onJNILoad не вызывается при вызове System.loadLibrary

extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) { 
    __android_log_print(ANDROID_LOG_INFO, __FUNCTION__, "onLoad"); 
    // some init code 
} 

мне нужно объявить JNI_OnLoad в определенном файле или объявить в Android.MK н сообщает системе, где найти метод JNI_OnLoad ли? Теперь я просто поместил один из многих .cpp-файлов.

сборник .so lib прилагается. Я пытаюсь сбрасывать такой файл, и я уверен, что метод JNI_OnLoad экспортируется. https://docs.google.com/file/d/0B089WeEZXTb3ZjZiQllaYThuUUk/edit

На самом деле, я пытаюсь передать библиотеку из источника android (libcorejava.so). Чтобы избежать конфликта классов, я уже меняю путь к классу.

А вот файл, который объявляет JNI_OnLoad: https://android.googlesource.com/platform/libcore/+/master/luni/src/main/native/Register.cpp Я уже изменить подпись на один выше, чтобы соответствовать стандартной подписи

EDIT: Я обнаружил, что андроид источник не загружает его по System.loadLibrary! Он говорит, что libcorejava используется для реализации System.loadLibrary, поэтому мы не можем использовать System.loadLibrary для его загрузки. Но в моем случае это не должно быть проблемой, так как мне нужна часть функции (связанная с ОИТ).

https://android.googlesource.com/platform/dalvik/+/master/vm/Init.cpp

// Most JNI libraries can just use System.loadLibrary, but you can't 
    // if you're the library that implements System.loadLibrary! 
    loadJniLibrary("javacore"); 
    loadJniLibrary("nativehelper"); 

EDIT 2:
Оказывается, что это происходит потому, что конфликт имен библиотеки! Но, похоже, для libjavacore требуется другая библиотека. Есть ли какой-либо инструмент, который может указать, что я не имею в виду?

java.lang.UnsatisfiedLinkError: Cannot load library: reloc_library[1286]: XXX 

EDIT 3:
TextClock новый API для отображения времени. Он существует только в 4.2+ api. Я пытаюсь сделать это, чтобы старший sdk мог его использовать. Это зависит от библиотеки ICU, которая находится в libjavacore. Поэтому я модифицирую файл Android.mk, чтобы убедиться, что libjavacore включает только исходный файл, связанный с icu, и окончательный скомпилированный файл, который будет включен в мой apk.

TextClock:
http://developer.android.com/reference/android/widget/TextClock.html

Он теперь работает в телефоне, который изначально поддерживает TextClock, но не работает в старых устройствах. Вот журнал исключений. Я думаю, это потому, что libjavacore является оберткой библиотеки ICU. Помимо обертки мне все равно нужно портировать библиотеку ICU. Но я собираюсь отказаться, как размер библиотеки ICU довольно большой и, кажется, не стоит за это ...

12-13 14:07:54.859: E/AndroidRuntime(2091): java.lang.UnsatisfiedLinkError: Cannot load library: reloc_library[1306]: 36 cannot locate '_ZN6icu_516Locale14createFromNameEPKc'... 
    12-13 14:07:54.859: E/AndroidRuntime(2091):  at java.lang.Runtime.loadLibrary(Runtime.java:370) 
    12-13 14:07:54.859: E/AndroidRuntime(2091):  at java.lang.System.loadLibrary(System.java:535) 
    12-13 14:07:54.859: E/AndroidRuntime(2091):  at com.example.time.MainActivity.onCreate(MainActivity.java:20) 
    12-13 14:07:54.859: E/AndroidRuntime(2091):  at android.app.Activity.performCreate(Activity.java:5008) 
    12-13 14:07:54.859: E/AndroidRuntime(2091):  at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1079) 
    12-13 14:07:54.859: E/AndroidRuntime(2091):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2023) 
    12-13 14:07:54.859: E/AndroidRuntime(2091):  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084) 
    12-13 14:07:54.859: E/AndroidRuntime(2091):  at android.app.ActivityThread.access$600(ActivityThread.java:130) 
    12-13 14:07:54.859: E/AndroidRuntime(2091):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195) 
    12-13 14:07:54.859: E/AndroidRuntime(2091):  at android.os.Handler.dispatchMessage(Handler.java:99) 
    12-13 14:07:54.859: E/AndroidRuntime(2091):  at android.os.Looper.loop(Looper.java:137) 
    12-13 14:07:54.859: E/AndroidRuntime(2091):  at android.app.ActivityThread.main(ActivityThread.java:4745) 
    12-13 14:07:54.859: E/AndroidRuntime(2091):  at java.lang.reflect.Method.invokeNative(Native Method) 
    12-13 14:07:54.859: E/AndroidRuntime(2091):  at java.lang.reflect.Method.invoke(Method.java:511) 
    12-13 14:07:54.859: E/AndroidRuntime(2091):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786) 
    12-13 14:07:54.859: E/AndroidRuntime(2091):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553) 
    12-13 14:07:54.859: E/AndroidRuntime(2091):  at dalvik.system.NativeStart.main(Native Method) 
+0

Включение его в один из многих файлов cpp в порядке. Я не знаю, в чем проблема, но я уверен, что это не причина. Единственное, что приходит мне на ум, это то, что вы забыли поставить extern «C» перед функцией. – eozgonul

+0

У меня нету. Зачем это нужно? – Bear

+0

http://stackoverflow.com/a/1041880/2359247 – eozgonul

ответ

1

Вы можете сбросить символы в вашем .so файл, используя readelf в папке компилированных инструментов , Убедитесь, что экспортировано JNI_OnLoad. Команда -s (символы) и имя .so-файла в вашей папке libs должны это сделать.

1

В старых версиях Android библиотека была напрямую связана с VM (libdvm.so, связанной с libnativehelper.so, которые были связаны с libjavacore.a). В последних выпусках this changed всегда загружать библиотеку во время запуска, используя механизм загрузки внутренней собственной библиотеки, поэтому при вызове JNI_OnLoad будет вызываться.

Если я бегу adb shell dalvikvm Foo (где «Foo» не существует), я вижу это в LogCat:

D dalvikvm: Trying to load lib libjavacore.so 0x0 
D dalvikvm: Added shared lib libjavacore.so 0x0 
D dalvikvm: Trying to load lib libnativehelper.so 0x0 
D dalvikvm: Added shared lib libnativehelper.so 0x0 
D dalvikvm: No JNI_OnLoad found in libnativehelper.so 0x0, skipping init 

Так загружен libjavacore.so и, видимо, нашел и побежал JNI_OnLoad (новостей не хорошая новость). Он загрузил libnativehelper.so и не нашел JNI_OnLoad, поэтому он зарегистрировал сообщение, чтобы сообщить вам об этом, если вы ожидали иначе.

Если заменить libjavacore.so в /system/lib (на корневое устройство) и выполнить команду dalvikvm, вы должны увидеть сообщение в файле журнала, вперемешку с сообщениями, как я показал выше. Если вы перезапустите систему, вы увидите свое сообщение во время запуска zygote, а не снова, если только что-то не запускает команду на основе Dalvik (например, am).

+0

Да ... если вы замените путь библиотеки или перепутаете исходный код * перед * любым вызовом функции exec(), инициализировали вещи с нуля. Но я подозреваю, что плакат вместо этого пытается упаковать свои собственные в свой .apk и загружать его явно, и это, вероятно, не работает, поскольку системная версия уже загружена в родительский зигот, прежде чем они попытаются загрузить их в процесс apkend-apk. –

+0

Ах. Если VM думает, что это тот же самый lib, в logcat должно быть сообщение «уже загружено»; если это не так, я бы ожидал, что 'JNI_OnLoad' просто будет работать (и новые методы для замены старого, потому что они используют явную регистрацию).Ваше предыдущее предложение переименовать общую библиотеку, вероятно, исправит ситуацию. – fadden

+1

@fadden Извините, я собираюсь портировать библиотеку вместо замены. Поэтому переименование работает. Спасибо всем вам, парень. – Bear

Смежные вопросы