Android JNI(android studio)의 동적 등록

이야기는 여기서 시작해야 합니다 - 정적 등록

비교가 없으면 해가 없습니다. 정적 등록은 탄생 이후 많은 비판을 받아왔습니다. 번거로운 프로세스(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으로 무장하면 진화에 의해 강화되어 클래스의 클래스 객체의 인스턴스가 됩니다. 동적 등록, 그게 바로 당신의 힘을 보여줄 때입니다.

동적 등록 프로젝트 구조 다이어그램

추천

출처blog.csdn.net/youyi300200/article/details/72841441