• 深入了解android平台的jni(一)


    android中很多Java类都具有native接口,这些接口由本地实现,然后注册到系统中。     
    主要的JNI代码放在以下的路径中:frameworks/base/core/jni/,这个路径中的内容被编译成库 libandroid_runtime.so,被放置在目标系统的/system/lib目录下。此外,android还有其他的 JNI库。JNI中的各个文件,实际上就是普通的C++源文件.
    如果要深入了解android framework层,则必须Android Native层运行及开发机制.
    这里先介绍一些native的基础知识

    1、接口定义
    _JNIEnv定义了一个虚拟机的接口,通过这个接口可以访问虚拟机的所有功能:
    1)分配对象(AllocObject/NewObject),并且控制对象的引用计数(NewGlobalRef/DeleteGlobalRef/DeleteLocalRef/IsSameObject/NewLocalRef)。
    2)获取类的定义(FindClass),并通过类的定义来获取获取类得方法和成员的ID(GetMethodID/GetFieldID)
    3)通过方法ID调用类的普通方法(CallObjectMethod)和静态方法(CallStaticObjectMethod)
    4)通过成员ID获取和设置类的普通成员(GetObjectField/SetObjectField)和静态成员(GetStaticObjectField/SetStaticObjectField)
    下面是比较常用的方法:
    1)查找该类:
       jclass xxx = (*env)->FindClass(env, "Lclass_name;");
    2)取得方法的id:
       jmethodID xxx = (*env)->GetMethodID(env, jclass, methodName, "(M)N");
    3)查找需要调用的该类的方法:
       jmethodID xxx = (*env)->GetMethodID(env, jclass, "(M)N" );
    4)取得静态方法的id
       jmethodID  xxx = (*env)->GetStaticMethodID(env,jclass, methodName,"(M)N")
    5)初始化该类的实例:  
       jobject xxx = (*env)->NewObject(env, jclass, jmethodID );
    6)调用实例的某方法: 
       (*env)->CallObjectMethod(env, jobject, jmethodID, [parameter1, parameter2,...] );
    7)释放实例: 
       (*env)->DeleteLocalRef(env, xxx);
    8)取得成员变量的id
       jfieldID xxx = (*env)->GetFieldID(env,jclass ,jfieldID,jfieldType) 
    9)取得静态成员变量的id
       jfieldID xxx = GetStaticFieldID(env,jclass ,jfieldID,jfieldType)
    JNIENV - java的运行环境
    jobject - 代表java的instance
    jclass - 代表java的类


    2、函数与属性签名
    在GetMethodID和GetFieldID这两个函数中,最后一个参数都是签名字符串,用来标示java函数和成员的唯一性。
    因为java中存在重载函数,所以一个函数名不足以唯一指定一个函数,这时候就需要签名字符串来指定函数的参数列表和返回值类型了。
    函数签名是一个字符串:"(M)N"
    括号中的内容是函数的参数类型,括号后面表示函数的返回值。

    3、JNI 类型签名
    "(M)N",这里的M和N指的是该函数的输入和输出参数的类型签名(Type Signature)。
    具体的每一个字符的对应关系如下
    字符 Java类型     C类型
    V      void       void
    Z    jboolean    boolean
    I      jint        int
    J      jlong      long
    D     jdouble     double
    F    jfloat       float
    B    jbyte        byte
    C    jchar        char
    S    jshort       short
    数组则以”["开始,用两个字符表示
    [I   jintArray    int[]
    [F   jfloatArray  float[]
    [B   jbyteArray   byte[]
    [C   jcharArray   char[]
    [S   jshortArray  short[]
    [D   jdoubleArray double[]
    [J   jlongArray   long[]
    [Z  jbooleanArray boolean[]
    如果Java函数的参数是class,则以”L”开头,以”;”结尾,中间是用”/” 隔开的包及类名。而其对应的C函数名的参数则为jobject
    一个例外是String类,其对应的类为jstring
    Ljava/lang/String; String jstring
    Ljava/net/Socket; Socket jobject
    如果JAVA函数位于一个嵌入类,则用$作为类名间的分隔符。
    例如 “(Ljava/lang/String;Landroid/os/FileUtils$FileStatus;)Z”
    举例说明"(M)N"的含义,例如:
    (I)V   带一个int 类型的参数,返回值类型为void
    ()D     没有参数,返回double

    本文欢迎转载,但请注明作者与出处:

    作者:流星

    出处:http://blog.sina.com.cn/staratsky

  • 相关阅读:
    win10安装vue
    通过docker安装rabbitmq
    python定时访问主机进程信息并反馈到远程服务器
    win10配置Apache+部署静态html页面
    HTTP协议—HTTP报文格式详解
    python脚本编写(纯干货)
    linux/CentOS的安装(萌新版)
    gradle中调用ant.unzip对zip包解压缩
    通过gradle运行测试脚本
    使用rest-assured测试rest service, 遇到“415 Unsupported Media Type”
  • 原文地址:https://www.cnblogs.com/aiguozhe/p/5355211.html
Copyright © 2020-2023  润新知