No JNI_OnLoad 문제 해결
04-29 13:53:12.184: D/dalvikvm(361): Trying to load lib/data/data/com.conowen.helloworld/lib/libHelloWorld.so 0x44edea98 04-29 13:53:12.204: D/dalvikvm(361): Added shared lib/data/data/com.conowen.helloworld/lib/libHelloWorld.so 0x44edea98
04-29 13:53:12.204: D/dalvikvm(361): No JNI_OnLoad found in/data/data/com.conowen.helloworld/lib/libHelloWorld.so 0x44edea98, skipping init
원리 설명:
Android의 응용층의 클래스는 모두 자바로 작성된 것입니다. 자바 클래스는Dex 파일로 컴파일된 후에 Dalvik 가상기기 (Virtual Machine) 에 의해 실행되어야 합니다.C&C++의 함수는 Dalvik 가상 기기에서 실행되는 것이 아니기 때문에 효율과 속도는 Dalvik 가상 기기에서 실행되는 것보다 훨씬 빠르다.만약 자바 프로그램을 실행할 때 C & C++ 함수를 불러와야 한다면, 불러오는 것은 어떤 과정입니까?
1. 자바는 Dalvik 가상 머신에게 로컬 C/C++ 라이브러리를 불러오라고 알립니다. 호출 함수: System.loadLibrary("Name");
2. Dalvik 가상 머신이 성공적으로 라이브러리를 불러오면 자동으로 라이브러리 안의 JNI를 찾습니다OnLoad 함수 - 로컬 메서드는 JNIOnLoad 함수, 일부 버전에서는 이 함수를 실현할 필요가 없습니다. 불러올 때 시스템의 기본 JNI 를 호출할 수 있습니다.OnLoad 함수.그러니까 만약에 라이브러리에 JNI가 안 적혀있다면...OnLoad() 함수는 VM에서 가장 오래된 JNI 1.1 버전을 기본적으로 사용합니다.그러나 새 버전의 JNI는 많은 확충을 했고 일부 내용도 최적화시켰다. JNI의 새 버전 기능을 사용해야 한다면 반드시 JNIOnLoad() 함수는 JNI 버전을 선언합니다.
(1) Dalvik VM 이 C 라이브러리에서 사용하는 JNI 버전을 알려줍니다.JNI가 없으면...OnLoad () 함수와 새로 확장된 jni 함수를 호출하면 Android 디버그 정보는 다음과 같습니다 (No JNI OnLoad found).
#include
#define LOG "TEST-L" // LOG
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG,__VA_ARGS__) // LOGD
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG,__VA_ARGS__) // LOGI
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN,LOG,__VA_ARGS__) // LOGW
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG,__VA_ARGS__) // LOGE
#define LOGF(...) __android_log_print(ANDROID_LOG_FATAL,LOG,__VA_ARGS__) // LOGF
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) {
JNIEnv* env = NULL;
jint result = -1;
if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
LOGE("jni_load failed
");
return result;
}
result = JNI_VERSION_1_4;
return result;
}
(2) Dalvik 가상 머신이 C 라이브러리를 불러올 때 첫 번째 일은 JNI 를 호출하는 것이기 때문이다OnLoad () 함수, 그래서 우리는 JNIOnLoad () 에서 JNI 함수 등록 등 초기화 작업을 진행합니다.로컬 함수를 등록하면 자바층이 로컬 함수를 호출하는 효율을 높일 수 있지만 이런 방법은android 원본에서 컴파일하는 데만 적응할 수 있다.다음은 C++ 버전의 로드 함수입니다.
jint JNI_OnLoad(JavaVM* vm, void* reserved) {
JNIEnv* env = NULL;// JNI Env
jint result = -1;
/*JavaVM::GetEnv jint (*GetEnv)(JavaVM*, void**, jint);
*/
if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
LOGE(ANDROID_LOG_ERROR, TAG, "GetEnv failed!");
return result;
}
LOGI(ANDROID_LOG_INFO, TAG, "loading . . .");
/*
* JNI env
* register_android_test_myclass_myffunc(env)
*/
if(register_android_test_myclass_myffunc(env) != JNI_OK) {
LOGE(ANDROID_LOG_ERROR, TAG,
"can't load register_android_test_myclass_myffunc");
goto end;
}
LOGI(ANDROID_LOG_INFO, TAG, "loaded");
result = JNI_VERSION_1_4;
return result;
}
static const char* const kClassPathName = "com/test/myclass";
static JNINativeMethod gMethods[] = {
{"setParam", "(Ljava/lang/String;)V", (void *)com_test_myclass_setParam},
{"prepare", "()V", (void *)com_test_myclass_prepare},
};
int register_android_test_myclass_myffunc(JNIEnv *env) {
return jniRegisterNativeMethods(env, kClassPathName, gMethods,
sizeof(gMethods) / sizeof(gMethods[0]));
/* OnLoad.cpp
* jint jniRegisterNativeMethods(JNIEnv* env,
const char* className,
const JNINativeMethod* gMethods,
int numMethods)
*/
}
참고:
여기서 AndroidRuntime::registerNativeMethods는 헤더 파일androidruntime/AndroidRuntime.h에서 정의, 사용 시
안드로이드에 있어야 돼.mk 파일에 더하기:
LOCAL_SHARED_LIBRARIES += \
libandroid_runtime
GetEnv () 함수가 반환되는 Jni 환경은 스레드마다 다릅니다.
Dalvik 가상 머신은 대개 Multi-threading이기 때문이다.스레드당 JNI 호출OnLoad() 시
사용하는 JNI Env는 다르므로 함수에 들어갈 때마다 vm->GetEnv를 통해 다시 가져와야 합니다.
(3) 및 JNIOnLoad() 함수에 해당하는 함수 JNIOnUnload(), VM이 C 라이브러리를 해제하면 JNI 호출OnUnload() 함수로 클린업 작업을 수행합니다.
/*
* ,
* ,
*
*/
void JNI_OnUnload(JavaVM* vm, void* reserved){
LOGI("call JNI_OnUnload ~~!!");
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.