이야기는 여기서 시작해야 합니다 - 정적 등록
비교가 없으면 해가 없습니다. 정적 등록은 탄생 이후 많은 비판을 받아왔습니다. 번거로운 프로세스(javah가 헤더 파일을 생성함)는 인터페이스가 추가될 때마다 슬래그가 h여야 합니다. 긴 함수 이름, 자세한 식별. 운영 효율이 낮다.처음 소통할 때 세부 신원에 따라 jni에서 해당 신원을 가진 사람을 찾는 것이 더 어렵다. 만약, 만약에, 결국에는 백합꽃이 모두 추웠다면. 힘들 때, 포기할 때, 남자가 무대에 등장할 때, 역동적인 등록, 그래 바로 그 사람이다. 자바 가상 머신에 등록된 JNI에 함수 매핑 테이블이 있는데 첫눈에 반하고 통신이 너무 원활합니다.
동적 등록, 원 몇 개 그리기
여전히 규칙이 있습니다. 조기에 데이터베이스를 구축하고 즉시 소통하십시오.
하나. 항목 JNI_OnLoad 메서드
System.loadLibrary는 JNI 동적 라이브러리를 로드한 후 JNI_OnLoad 함수를 호출하여 동적 등록을 시작합니다. 여기가 등록하는 곳입니다 엉뚱한 곳을 찾을 수 없습니다 도둑을 잡으려고 경찰에 신고하면 119에 전화해야 합니다. 참고: 하나의 .so에는 하나의 onload 메서드만 있을 수 있습니다.
둘. RegisterNatives 메서드의 하이라이트
JNI 제국에서 JVM의 대변인 JNIEnv*를 소개해야 하는데 자바에서 사활을 건 권력을 쥐고 있다. JVM과 상호 작용하고 Java 객체로 작업합니다. 기능. 그리고 RegisterNatives는 폰 중 하나인 레지스트라일 뿐입니다. 그러나 그를 통해서만 기능 매핑 테이블에 들어갈 수 있습니다. 함수 맵? 걱정하지 말고 시간을내어 그의 마음을 차근차근 벗겨 봅시다. jni.h 제국에는 설명에 다음과 같은 단락이 있습니다.
typedef struct {
const char* name; //Java中函数的名字
const char* signature; //描述了函数的参数和返回值
void* fnPtr; //函数指针,指向我们调用别人家c++的封装 JNI 函数方法
} JNINativeMethod;
함수 매핑 테이블의 데이터 구조입니다 주석을 추가하면 설명할 것이 없을 것 같습니다 지루한 소스 코드 파싱에 대해 이 구조는 어떻게 사용됩니까? 기침 기침, 주제로 돌아가서 RegisterNatives의 하이라이트, 이것은 법정 서사극, 세심한 레이아웃, 웅장한 장면입니다. 말하자면 네가 죽든가 내가 죽든가 하는 이야기의 결말에 함께 출연할 배우는 A, B, C 단 세 명뿐이다. 이 구절은 대본에 기록되어 있습니다.
/**
* 向JNI环境注册一个本地方法
* @param clazz 包含本地方法的Java类
* @param methods 本地方法描述数组
* @param nMethods 本地方法个数
* @return 成功返回0,否则注册失败
*/
jint RegisterNatives(jclass clazz, const JNINativeMethod *methods, jint nMethods);
자신도 모르게 댓글이 분석을 완료합니다. 단순하게 유지하고 말하는 방식을 단순하게 유지하십시오. 당신의 공연에 협조해야 할 나는 눈을 감는다. 레지스트라의 설명은 대략 동일합니다.더 필요한 사항이 있으면 직접 조사하십시오.
삼. JNI_OnUnload 메서드 종료
놀러 나온 사람들은 조만간 갚아야 할 것이고 거대한 JNI 제국은 언젠가는 끝날 것입니다. VM이 컴포넌트를 해제하면 JNI_OnUnload 메서드를 호출하게 되는데 객체 등 자신이 한때 소유했던 모든 객체는 이곳의 대지로 돌아가 봄 진흙으로 변해 꽃을 보호한다. 물론 포기하고 이 방법을 제쳐두기로 선택할 수도 있습니다. 그러면 언젠가는 독버섯이 번성하고 천천히, 그리고 나서 붐을 일으킬 것입니다. 최적화는 귀하와 저를 위한 옵션입니다.
넷. 기적의 목격자 순간
지금 이 순간 저는 매우 흥분됩니다. 꽃아, 너는 왜 이렇게 붉니? 약간의 세부 정보를 포함하여 코드를 약간 붙여넣습니다.
static const char *jniClassName = "net/mapout/jni/JNILoader";
static JNINativeMethod methods[] = {
{
"sayHello", "()Ljava/lang/String;", (void*)jniSayHello},
};
static int registerNatives(JNIEnv* env) {
jclass clazz = env->FindClass(jniClassName);
if (clazz == NULL)
return JNI_FALSE;
jint methodSize = sizeof(methods) / sizeof(methods[0]);
if ( env->RegisterNatives(clazz, methods, methodSize) < 0 )
return JNI_FALSE;
return JNI_TRUE;
}
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
JNIEnv* env = NULL;
jint result = -1;
if (vm->GetEnv((void **)&env, JNI_VERSION_1_6) != JNI_OK)
return JNI_ERR;
//注册方法
if (!registerNatives(env))
return JNI_ERR;
result = JNI_VERSION_1_6;
return result;
}
JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *vm, void *reserved) {
JNIEnv *env = nullptr;
jint ret = vm->GetEnv(reinterpret_cast<void **>(&env), JNI_VERSION_1_6);
if (ret != JNI_OK) {
return ;
}
//回收二手女朋友,回收... 嘿嘿嘿
}
언뜻 보기에 우리가 유지해야 할 것은 메서드 배열이고 나머지는 복사 및 붙여넣기입니다. 약간의 비교를 위해:
/**
* 动态注册。命名简洁,清晰明了
*/
jstring jniSayHello(JNIEnv *env, jobject obj){
return str2jstring( env, sayHello() );
}
/**
* 静态注册。噗噗噗,一口老血喷涌而出
*/
JNIEXPORT jstring JNICALL Java_net_mapout_jni_JNILoader_sayHello
(JNIEnv *env, jclass jclass){
return str2jstring( env, sayHello() );
}
또 다른 참고 사항입니다. 코드의 경우 명확하지 않은 주석은 없으며, 있는 경우 두 개의 주석을 사용하십시오. 세부 사항에 대해 이야기하기 위해 여기의 함수에는 2개의 매개 변수, JNIEnv *가 설명되어 있고 jobject가 있습니다. 조금 말하자면, 네이티브 메서드에 static이 없으면 클래스의 인스턴스이고, static으로 무장하면 진화에 의해 강화되어 클래스의 클래스 객체의 인스턴스가 됩니다. 동적 등록, 그게 바로 당신의 힘을 보여줄 때입니다.