zoukankan      html  css  js  c++  java
  • [卷I]第2章 深入理解JNI

    JAVA世界 MediaScanner MediaScanner.java

    native_init();

    processFile();

    JNI层 libmedia_jni.so android_media_mediaScanner.cpp android_media_MediaScanner_native_init
    Natvie世界 libmedia.so    

    关注:native_init 与 android_media_MediaScanner_native_init是如何对应的?注册。

    注册有静态注册和动态注册两种:

    1、静态注册,编写MediaScanner.java java -o javah -o 生成android_media_MediaScanner.h

    JNIEXPORT void JNICALL Java_android_media_MediaScanner_native_linit

    JNIEXPORT void JNICALL Java_android_media_MediaScanner_processFile

    2、动态注册

    由结构体JNINativeMethod保存对应关系

    由register_android_media_MediaScanner(JNIEnv *env) 调用注册函数

    而register_android_media_MediaScanner由JNI_OnLoad调用(JNI_OnLoad需要自己实现)

    因为:当JAVA层通过System.loadLibrary加载完JNI动态库后,紧接着就会查找库中的JNI_OnLoad函数。

    2.4.3 JNIEnv介绍

    JNIEnv 与线程相关的代表JNI环境的结构体。

    JNIEnv一般都是native函数转换成JNI层函数后由虚拟机传进来的,可以直接使用。

    但如果是后台线程收到一个网络消息,而又需要由native层函数主动回调Java层函数时,JNIEnv从何而来?

    注意:

    jint JNI_OnLoad(JavaVM* vm, void* reserved)

    一个进程对应一个JavaVM,即JavaVM是与进程相关的。

    调用JavaVM的AttachCurrentThread函数,就可得到这个线程的JNIEnv结构体。另外,在后台线程退出前,需要调用JavaVM的DetachCurrentThread函数来释放对应的资源。

    2.4.4 通过JNIEnv操作jobject

    先写一下体会:

    在JNI层,先通过GetFieldID,取得在Java层定义的成员变量,如mNativeContext(在MediaScanner.java中private int mNativeContext;)

    给jfieldID:fields.context = env->GetFieldID(clazz, "mNativeContext", "I");

    且fields是文件中的全局变量。

    在Java层会通过native函数调用,到JNI层调用设置来设置Java层的mNativeContext。(呵呵,这是用下层的方法设置自己层的变量啊)。

    MediaScanner.java native_setup();

    android_media_MediaScanner.cpp android_media_MediaScanner_native_setup env->SetIntField(thiz, fields.context, (int)mp);

    当然,设置好后,JNI层可以通过(MediaScanner *)env->GetIntField(thiz, fields.context);直接使用。

    在MediaScanner.java中,代码逻辑非常明确:

    加载完jni库后调用native_init,会让jni层取得mNativeContext

    创建MediaScanner对象时,会调用native_setup,将StagefrightMediaScanner对象指针给mNativeContext;

    对象销毁时,调用native_finalize,将mNativeContext设为0。

    ------------------------------------------------------------------------------------------------------------

    JNI层会用jobject来表示对象的数据类型。

    在JNI规则中,用jfiledID和jmethodID来表示Java类的成员变量和成员函数,可通过JNIEnv的下面两个函数得到:

    jfieldID GetField(jclass clazz, const char * name, const char *sig);

    jmethodID GetMethodID(jclass clazz, const char * name, const char *sig);

    jclass代表java类,name表示成员函数或成员变量的名字,sig为这个函数和变量的签名信息。

    调用 GetMethodID 保存为成员变量,为了程序运行效率。

            mScanFileMethodID = env->GetMethodID(
                                        mediaScannerClientInterface,
                                        "scanFile",
                                        "(Ljava/lang/String;JJZZ)V");

    取得Java对象的方法scanFile。

            mEnv->CallVoidMethod(mClient, mScanFileMethodID, pathStr, lastModified,
                    fileSize, isDirectory, noMedia);

    CallVoidMethod是调用Java对象的函数scanFile。

    2.4.5 jstring介绍

    调用JNIEnv的NewString(JNIEnv *env, const jchar* unicodeChars, jsize len),可以从Native的字符串得到一个jstring对象。

    调用JNIEnv的NewStringUTF将根据Native的一个UTF-8字符串得到一个jstring对象。

    GetStringChars GetStringUTFChars 可以将Java String对象转换成本地字符串。

    需要调用ReleaseStringChars ReleaseStringUTFChars释放资源, 否则会导致JVM内存泄露。

    2.4.7 垃圾回收

    JNI技术一共提供三种类型的引用:

    Local Reference 本地引用,一旦JNI层函数返回,就可能被垃圾回收。

    Global Reference 全局引用,不主动释放,永远不会被回收。

    Weak Global Reference 弱全局引用,一种特殊的Global Reference,在运行中可能被回收,所以在使用之前需要调用JNIEnv的IsSameObject判断。

    根据Local Reference的说明,函数返回后,对象就会被回收,看起来调用DeleteLocalRef是多余的,其实,调用DeleteLocalRef是立即回收。

    所以,没有及时回收Local Reference或许是进程占用内存过多的一个原因。

  • 相关阅读:
    Django Rest Framework 教程及API向导
    zabbix2.4升级到2.5 --考虑升级到zabbix3.0
    followme_laser包解读
    ROS多个工作空间存在同名包的BUG
    fatal err Eigen/Dense No such file or directory(unsupported/Eigen/FFT、Eigen/Core也是一样的道理)
    ROS向节点传递参数的方法总结(rosrun,launch) + (参数服务器,main函数参数)
    同步Sublime Text配置
    W: Failed to fetch http://packages.microsoft.com/repos/vscode/dists/stable/main/binary-amd64/Package
    Ubuntu(Linux)下更新CMake,最安全的更新
    Ignoring Provides line with DepCompareOp for package gdb-minimal
  • 原文地址:https://www.cnblogs.com/jimwind/p/3414484.html
Copyright © 2011-2022 走看看