• Jni规范


    一、 JNI概述

    JavaNative Interface的缩写,中文为Java本地调用。从Java1.1开始,JNI即成为Java标准的一部分。

    JNI设计的目的是为了允许Java代码与其他语言进行交互。但这样做通常会导致丧失平台可移植性,通常是在特定的需求下进行,例如使用旧的其他语言的库、需要获得Java类库不支持的某种基于具体平台的特性、大量数学计算性能优化等。

    二、 JNI数据类型和数据结构

    1.基本类型

    JNI基本类型和本地等效类型的对应表格如下:

    Java类型 本地类型 说明
    boolean jboolean 无符号,8位
    byte jbyte 无符号,8位
    char jchar 无符号,16位
    short jshort 有符号,16位
    int jint 有符号,32位
    long jlong 有符号,64位
    float jfloat 32位
    double jdouble 64位
    void void

    为了使用方便,还提供了如下定义:

    #define JNI_FALSE 0

    #define JNI_TRUE 1

    Jsize类型用于描述主要指数和大小:

    typedef jint jsize;

    2.引用类型

    除了基本类型外,JNI还包含了很对对应于不同Java对象的引用类型,JNI引用类型的组织层次如下图所示:

    c语言中,所有其他JNI引用类型都被定义为与jobject一样,例如:

    typedef jobject jclass;

    在C++中,JNI引入虚构类以加强子类关系,例如:

    class _jobject{};

    class _jstring : public jobject{};

    typedef _jobject jobject;

    typedef _jstring jstring;

    3.方法ID和域ID

    方法ID和域ID是常规的C指针类型:

    struct_jmethodID; /*不透明结构*/

    typedefstruct _jmethodID *jmethodID; /*方法ID*/

    struct_jfieldID; /*不透明结构*/

    typedefstruct _jfieldID *jfieldID /*域ID*/

    4.值类型

    jvalue联合在参数数组中用作单元类型,其声明如下:

      typedefunion _jvalue
    {
        jboolean z;
        jbyte b;
        jchar c;
        jshort s;
        jint i;
        jlong j;
        jfloat f;
        jdouble d;
        jobject l;
    }jvalue;

    5.UTF8字符串

    JNI的UTF8字符串与标准UTF8格式有两个区别,第一,空字节0使用双字节格式进行编码,而不是标准UTF8的单字节;第二,只使用单字节、双字节和三字节格式,不支持更长的字节格式。

    三、 JNI接口函数命名方式

    1. 类型签名

    Java虚拟机的类型签名如下:

    类型签名 Java类型
    Z boolean
    B byte
    C char
    S short
    I int
    J long
    F float
    D double
    Lfully-qulitied-class; 全限定类
    [type type[] 数组
    (argtypes)rettype 方法类型

    例如,Java方法int feet(int n, String s,int [] arr)的类型签名如下:

    (ILJava/lang/String;[I)I

    圆括号里面为参数,I表示第一个参数int型,LJava/lang/String;表示第二个参数为全限定Java.lang.String类型,[I表示第三个参数为int型的数组,圆括号后面为返回值类型,I表示返回值为int型。

    2. 一般函数的JNI接口函数命名方式

    一般JNI接口函数命名如下:

    Java_包名_类名_方法名。

    例如:某工程下Sample/test包下MySigal类的int GetASample()方法的C语言实现函数命名如下:

    jint Java_Sample_test_MySigal_GetASample(JNIEnv* env,jobjectobj)

    其中,包名所包含的“/”应全部以下划线替代,其本地实现的参数和返回值也应转换为JNI类型。

    3. 重载函数的JNI接口函数命名方式

    重载函数的JNI实现在一般函数的JNI实现之外,还应添加上类型签名以作为同名函数之间的区别,其接口函数命名如下:

    Java_包名_类名_方法名_参数签名。

    例如:某工程下Sample/test包下MySigal类的int GetASample(int n, String s,int [] arr)方法的C语言实现函数命名如下:

    jintJava_Sample_test_MySigal_GetASample_ILJava_lang_String_2_3I

    (JNIEnv*env, jobject obj, jint n, jstring s, jintarray arr)。

    JNI在函数命名时采用名字扰乱方案,以保证所有的Unicode字符都能转换为有效的C函数名,所有的“/”,无论是包名中的还是全限定类名中的,均使用“_”代替,用_0,…,_9来代替转义字符,如下:

    转义字符序列 表示
    _0XXXX Unicode字符XXXX
    _1 字符“_”
    _2 签名中的字符“;”
    _3 签名中的字符“[”

    四、 JNI函数与API

    在目前的应用中,我们所主要需要关心的是C/C++数据类型与JNI本地类型之间的转化过程,这个过程某些数据的转换需要使用JNIEnv对象的一系列方法来完成。

    1.jstring转换为C风格字符串

    char* test = (char*)(*env)->GetStringUTFChars(env,jstring,NULL);

    使用完毕后,应调用:

    (*env)->ReleaseStringUTFChars(env,jstring, test);

    释放资源。

    2.C风格字符串转换为jstring

    char charStr[50];

    jstring jstr;

    jstr = env ->NewStringUTF(charStr);

    3.C语言中获取的一段char*的buffer传递给Java

    在jni中new一个byte数组,然后使用

    (*env)->SetByteArrayRegion(env,bytearray, 0, len, buffer)

    操作将buffer拷贝到数组中。

    这种方式主要是针对buffer中存在“”的情况,如果以C风格字符串的方式读入,就会损失“”之后的字符。

    4.数组操作

    数组操作的相关函数列表如下:

    JNI函数 功能
    GetArrayLength 返回数组中的元素数
    NewObjectArray 创建一个指定长度的原始数据类型数组
    GetObjectArrayElement 返回Object数组的元素
    SetObjectArrayElement 设置Object数组的元素
    GetObjectArrayRegion 将原始数据类型数组中的内容拷贝到预先分配好的内存缓存中
    SetObjectArrayRegion 设置缓存中数组的值
    ReleaseObjectArrayRegion 释放GetObjectArrayRegion分配的内存

    对int,char等基本数据类型的数组操作,将相关Object名称替换为对应基本数据类型名称即为相关函数。

    数组操作的方法选择基于使用者的需求而定,如果使用者需要在内存中拷贝数组并对其进行操作那么一般使用GetObjectArrayRegion和SetObjectArrayRegion函数,否则一般使用SetObjectArrayElement和GetObjectArrayElement函数

  • 相关阅读:
    11g 配置 dgmgrl 以及报错 DataGuard ORA-00313,
    java三种匿名的方式开启线程
    java 四种方式实现字符流文件的拷贝对比
    java中过滤查询文件
    通过Java实现斗地主
    java中Map的entrySet 和keySet的使用
    python3列表推导式和生成器。
    python的特殊方法总结
    python3 定义向量运算
    python3模拟扑克牌
  • 原文地址:https://www.cnblogs.com/xiaoxiaoshen/p/5296235.html
Copyright © 2020-2023  润新知