zoukankan      html  css  js  c++  java
  • Android有关JNI 学习(两)为JNI方法名称,数据类型和方法签名的一些知识

    我们知道,使用javah产生c/c++当在头文件,将java定义 native 功能,以产生相应jni层功能,如下面:

    /* 
     * Class:     com_lms_jni_JniTest 
     * Method:    getTestString 
     * Signature: ()Ljava/lang/String; 
     */  
    JNIEXPORT jstring JNICALL Java_com_lms_jni_JniTest_getTestString  
      (JNIEnv *, jobject);  

    我们能够看到方法名是以Java_com_lms_jni等开头的。还有什么所谓的Signature。那这些事实上都是什么意思呢。今天我们就来简单地认识一下。

    JNI 命名规则

    对于传统的JNI编程来说,JNI方法跟Java类方法的名称之间有一定的相应关系。要遵循一定的命名规则,例如以下:

    1) 前缀: Java_
    2) 类的全限定名。用下划线进行分隔(_):com_lms_jni_JniTest
    3) 方法名:getTestString                                             
    3) jni函数指定第一个參数:  JNIEnv *
    4) jni函数指定第二个參数:  jobject
    5) 实际Java參数:               jstring, jint ....
    6) 返回值的參数 :                 jstring, jint.... 
    所以对于在Java类 com.lms.jni.HwDemo中的一个方法:
    public native String addTail(String tail);

    其相应的jni层的方法例如以下:
    jstring Java_com_lms_jni_HwDemo_addTail(JNIEnv * e, jobject clazz, jstring tail);

    假设不这样命名,当把动态库载入进DVM的时候,通过JNIEnv *指针去查找Java Native方法相应的JNI方法的时候。就会找不到了。


    注意,我们也能够利用函数注冊的方法,将Java层的方法名跟JNI层的方法名的相应关系保存起来。注冊到DVM中,就不须要这种命名规范了。



    JNI 数据类型


    我们知道Java的数据类型是跟C/C++的数据类型是不一样的,而JNI是处于Java和Native本地库(大部分是用C/C++写的)中间的一层,JNI对于两种不同的数据类型之间必须做一种转换,所以在JNI跟Java之间就会有数据类型的相应关系。

    在JNI中。提供了下面各种数据类型,能够分为原生类型和引用类型:
    对于原生类型有:jchar, jbyte, jshort, jint, jlong, jfloat, jdouble, jboolean,其与java端的数据类型相应例如以下表:

    java jni
    char jchar
    byte jbyte
    short jshort
    int jint
    long jlong
    float jfloat
    double jdouble
    boolean jboolean

    对于引用类型则有:jobject, jstring, jthrowable, jclass, jarray, 以及继承于jarray。相应于其原生类型的8种j<type>array和jobjectarray。



    知道了不同的数据类型的转换关系。我们就知道在什么情况下,应该对数据进行怎么样的处理。

    JNI方法签名



    为什么会有方法签名这样的东西呢?这是由于Java这边支持函数重载,即尽管參数不一样。可是方法名一样,那么在JNI层它们的方法名都会是一样的,那JNI也会犯迷糊了。得找哪个呢?
    只是也正是由于其參数类型是不一样的。所以就出现了方法签名。利用方法签名和方法名来唯一确定一个JNI函数的调用。
    既然方法签名是基于參数类型的不同而形成的,首先要知道Java各数据类型相应的签名是什么,也就是所谓的类型签名,
    在jni.h文件里就已经定义了这样一套规则,例如以下:
    typedef union jvalue {
        jboolean    z;
        jbyte       b;
        jchar       c;
        jshort      s;
        jint        i;
        jlong       j;
        jfloat      f;
        jdouble     d;
        jobject     l;
    } jvalue;

    相应于Java端的数据类型,我们也能够看一下以下的表:

    Java 类型 类型签名
    boolean Z
    byte B
    char C
    short S
    int I
    long L
    float  F
    double D
    L全限定名;,比方String, 其签名为Ljava/lang/util/String;
    数组 [类型签名, 比方 [B

    对于上面的类,要注意其后面另一个分号。
    而对一个方法,其签名就是其參数类型签名和返回值类型签名的字符串,其形式例如以下:

    (类型签名1类型签名2...)返回值类型签名

    每一个类型签名之间是没有空格的。以下看看两个样例:

    有方法 1):
    public string addTail(String tail, int index)

    其相应的签名例如以下:

    (Ljava/util/String;I)Ljava/util/String;

    方法 2):
    public int addValue(int index, String value,int[] arr)

    其相应的签名例如以下:
    (ILjava/util/String;[I)I

    相信通过这两个样例,大家也可以了解了方法签名是什么样的形式了吧,对于JNI这些奇形怪状的表示形式也有一定的了解了。

    结束。

    版权声明:本文博客原创文章,博客,未经同意,不得转载。

  • 相关阅读:
    设计模式
    Lambda表达式
    网络通信
    排序
    可变参数
    反弹shell学习总结
    Apache Flink任意Jar包上传导致远程代码执行漏洞复现
    定时执行rsync同步数据以及mysql备份
    python练习
    django 模型生成sql(多对多)
  • 原文地址:https://www.cnblogs.com/bhlsheji/p/4646079.html
Copyright © 2011-2022 走看看