`
mmdev
  • 浏览: 12890715 次
  • 性别: Icon_minigender_1
  • 来自: 大连
文章分类
社区版块
存档分类
最新评论

技术转载:Jni学习二:JNI 数据类型

 
阅读更多

转自:http://wxiaolei.blog.163.com/blog/static/10387601200841762812328/

通过本章可以了解c文件如何使用java复杂的数据类型。

从Java 1.1开始,Java Native Interface (JNI)标准成为java平台的一部分,它允许Java代码和其他语言写的代码进行交互。JNI一开始是为了本地已编译语言,尤其是C和C++而设计 的,但是它并不妨碍你使用其他语言,只要调用约定受支持就可以了。让我们看一些使用JNI的简单例子吧。

使用java与本地已编译的代码交互,通常会丧失平台可移植性。但是,有些情况下这样做是可以接受的,甚至是必须的,比如,使用一些旧的库,与硬件、操作系统进行交互,或者为了提高程序的性能。JNI标准至少保证本地代码能工作在任何Java 虚拟机实现下。

开始:

如果你习惯了使用JNI,你就不会觉得它难了。既然本地方法是由其他语言实现的,它们在Java中没有函数体。但是,所有本地代码必须用本地关键词 声明,成为Java类的成员。清单A演示了一个简单的类,它申明了一个本地的(native),静态的(static)方法:sum。

写完了你的Java类,接下来就要写本地代码。本地方法符号提供一个满足约定的头文件,使用Java工具可以很容易地创建它而不用手动去创建。你对 Java的class文件使用javah命令,就会为你生成一个对应的C/C++头文件。清单B就是为清单A的Test1类创建的头文件。注意:它创建了 一个C/C++函数:Java_Test1_sum。

执行本地方法:

一旦你有了这个头文件,你就需要写头文件对应的本地方法,就像我在清单C做的那样。注意:所有的本地方法的第一个参数都是指向JNIEnv结构的。 这个结构是用来调用JNI函数的,(我会在另一个章节中讨论)。第二个参数jclass的意义,要看方法是不是静态的(static)或者实例 (Instance)的。前者,jclass代表一个类对象的引用,而后者是被调用的方法所属对象的引用。最后的两个jint参数表示了Java方法的 int参数。

返回值和参数类型根据等价约定映射到本地C/C++类型,如表A所示。有些类型,如清单B里面的两个jint参数,在本地代码中可直接使用,而其他类型只有通过JNI调用操作。

表A

Java类型 本地类型 描述
boolean jboolean C/C++8位整型
byte jbyte C/C++带符号的8位整型
char jchar C/C++无符号的16位整型
short jshort C/C++带符号的16位整型
int jint C/C++带符号的32位整型
long jlong C/C++带符号的64位整型e
float jfloat C/C++32位浮点型
double jdouble C/C++64位浮点型
Object jobject 任何Java对象,或者没有对应java类型的对象
Class jclass Class对象
String jstring 字符串对象
Object[] jobjectArray 任何对象的数组
boolean[] jbooleanArray 布尔型数组
byte[] jbyteArray 比特型数组
char[] jcharArray 字符型数组
short[] jshortArray 短整型数组
int[] jintArray 整型数组
long[] jlongArray 长整型数组
float[] jfloatArray 浮点型数组
double[] jdoubleArray 双浮点型数组

※ JNI类型映射

最后一步是把本地代码编译成共享库(比如,UNIX的so文件,Windows的dll文件)。在Java中调用方法前,共享库须通过System.loadLibrary导入。最常用的方式是在类的静态(static)初始化器里做这这个工作。


在本地代码中访问JNI

我举的例子很简单,并不能满足演示怎样写JNI方法的目标。现在,让我们看一些高级的,通过JNIEnv结构使用非简单类型的例子。

JNI通过函数的形式提供了很多功能,供本地代码通过指向JNIEnv结构的指针调用;它作为第一个参数传递给每个本地方法。JNI函数的调用有下面几种格式(这里,假设env是指向JNIEnv的指针):

//C 格式

(*env)-><jni function>( env, <parameters> )

//C++ 格式

env-><jni function>( < parameters> )

这篇文章中接下来的例子我将会用C++格式。

使用数组:

JNI通过JNIEnv提供的操作Java数组的功能。它提供了两个函数:一个是操作java的简单型数组的,另一个是操作对象类型数组的。

因为速度的原因,简单类型的数组作为指向本地类型的指针暴露给本地代码。因此,它们能作为常规的数组存取。这个指针是指向实际的Java数组或者Java数组的拷贝的指针。另外,数组的布置保证匹配本地类型。

为了存取Java简单类型的数组,你就要要使用GetXXXArrayElements函数(见表B),XXX代表了数组的类型。这个函数把Java数组看成参数,返回一个指向对应的本地类型的数组的指针。

表B

函数 Java数组类型 本地类型
GetBooleanArrayElements jbooleanArray jboolean
GetByteArrayElements jbyteArray jbyte
GetCharArrayElements jcharArray jchar
GetShortArrayElements jshortArray jshort
GetIntArrayElements jintArray jint
GetLongArrayElements jlongArray jlong
GetFloatArrayElements jfloatArray jfloat
GetDoubleArrayElements jdoubleArray jdouble

JNI数组存取函数

当你对数组的存取完成后,要确保调用相应的ReleaseXXXArrayElements函数,参数是对应Java数组和 GetXXXArrayElements返回的指针。如果必要的话,这个释放函数会复制你做的任何变化(这样它们就反射到java数组),然后释放所有相 关的资源。

为了使用java对象的数组,你必须使用GetObjectArrayElement函数和SetObjectArrayElement函数,分别去get,set数组的元素。GetArrayLength函数会返回数组的长度。

清单D包含了一个简单的类,它演示了本地代码如何使用Java数组。这个本地实现循环遍历一个整型(int)数组,返回这些元素的总和。为简单起见,这个清单包含了java代码和本地实现。我已经省略了头文件,它可以很方便地通过javah得到。


在本地代码中访问JNI

使用对象

详细请参照:Jni学习三:jni使用对象详解

JNI提供的另外一个功能是在本地代码中使用Java对象。通过使用合适的JNI函数,你可以创建Java对象,get、set 静态(static)和实例(instance)的域,调用静态(static)和实例(instance)函数。JNI通过ID识别域和方法,一个域或 方法的ID是任何处理域和方法的函数的必须参数。

表C列出了用以得到静态(static)和实例(instance)的域与方法的JNI函数。每个函数接受(作为参数)域或方法的类,它们的名称,符号和它们对应返回的jfieldID或jmethodID。

表C

函数 描述
GetFieldID 得到一个实例的域的ID
GetStaticFieldID 得到一个静态的域的ID
GetMethodID 得到一个实例的方法的ID
GetStaticMethodID 得到一个静态方法的ID

※域和方法的函数

如果你有了一个类的实例,它就可以通过方法GetObjectClass得到,或者如果你没有这个类的实例,可以通过FindClass得到。符号是从域的类型或者方法的参数,返回值得到字符串,如表D所示。

表D

Java 类型 符号
boolean Z
byte B
char C
short S
int I
long L
float F
double D
void V
objects对象 Lfully-qualified-class-name;L类名
Arrays数组 [array-type [数组类型
methods方法 (argument-types)return-type(参数类型)返回类型

※确定域和方法的符号

一旦你有了类和方法或者域的ID,你就能把它保存下来以后使用,而没有必要重复去获取。

有几个分别访问域和方法的函数。实例的域可以使用对应域的GetXXXField的变体函数访问。GetStaticXXXField函数用于静态类型。设置域的值,用SetXXXField 和SetStaticXXXField函数。表E包含了所有访问域的函数列表。

表E

Java 类型 Method方法
boolean GetBooleanField, GetStaticBooleanField, SetBooleanField,SetStaticBooleanField
byte GetByteField, GetStaticByteField, SetByteField, SetStaticByteField
char GetCharField, GetStaticCharField, SetCharField, SetStaticCharField
short GetShortField, GetStaticShortField, SetShortField, SetStaticShortField
int GetIntField, GetStaticIntField, SetIntField, SetStaticIntField
long GetLongField, GetStaticLongField, SetLongField, SetStaticLongField
float GetFloatField, GetStaticFloatField, SetFloatField, SetStaticFloatField
double GetDoubleField, GetStaticDoubleField, SetDoubleField, SetStaticDoubleField
object GetObjectField, GetStaticObjectField, SetObjectField, SetStaticObjectField

※访问域的函数

另外,方法的访问是由CallXXXMethod 函数和CallStaticXXXMethod函数完成的,XXX表明了方法的返回值类型。这些函数的变体允许传递数组参数 (CallXXXMethodA and CallStaticXXXMethodA)或者传递一个可变大小的列表(CallXXXMethodV and CallStaticXXXMethodV)。


一个完整的列表

表F:一个完整的列表

返回类型 函数
boolean CallBooleanMethod, CallBooleanMethodA, CallBooleanMethodV, CallStaticBooleanMethod, CallStaticBooleanMethodA, CallStaticBooleanMethodV
byte CallByteMethod, CallByteMethodA, CallByteMethodV, CallStaticByteMethod, CallStaticByteMethodA, CallStaticByteMethodV
char CallCharMethod, CallCharMethodA, CallCharMethodV, CallStaticCharMethod, CallStaticCharMethodA, CallStaticCharMethodV
short CallShortMethod, CallShortMethodA, CallShortMethodV, CallStaticShortMethod, CallStaticShortMethodA, CallStaticShortMethodV
int CallIntMethod, CallIntMethodA, CallIntMethodV, CallStaticIntMethod, CallStaticIntMethodA, CallStaticIntMethodV
long CallLongMethod, CallLongMethodA, CallLongMethodV, CallStaticLongMethod, CallStaticLongMethodA, CallStaticLongMethodV
float CallFloatMethod, CallFloatMethodA, CallFloatMethodV, CallStaticFloatMethod, CallStaticFloatMethodA, CallStaticFloatMethodV
double CallDoubleMethod, CallDoubleMethodA, CallDoubleMethodV, CallStaticDoubleMethod, CallStaticDoubleMethodA, CallStaticDoubleMethodV
void CallVoidMethod, CallVoidMethodA, CallVoidMethodV, CallStaticVoidMethod, CallStaticVoidMethodA, CallStaticVoidMethodV
object CallObjectMethod, CallObjectMethodA, CallObjectMethodV, CallStaticObjectMethod, CallStaticObjectMethodA, CallStaticObjectMethodV

※方法访问函数

清单E演示了如何在本地代码中调用方法。本地方法printRandom得到了静态方法Math.random的ID,并且调用它几次,打印出结果。实例方法也一样处理。

分享到:
评论

相关推荐

    JNI完全技术手册 带完整书签

    7、实例七:jni函数中传递基本数据类型参数... 62 8、实例八:在jni函数中传递对象类型参数... 62 9、实例九:在jni函数中处理字符串... 63 10、实例十:在jni函数中处理数组... 64 11、实例十一:在jni中的...

    jni数据类型转换

    jni数据类型转换例程 1. java向native传递常用基本数据类型 和字符串类型 2. java向native传递数组类型 3. java向native传递自定义java对象 4. java向native传递任意java对象(以向native传递ArrayList为例) 5....

    jni开发中所需的头文件:jni.h、jni_md.h

    在windows环境下的jni.h jni_md.h文件。 实际上是从jdk1.8安装完毕后,从文件夹下取得的。 jni.h在【jdk1.8.0_144\include】路径下。 jni_md.h在【jdk1.8.0_144\include\win32】路径下(linux版把win32换成linux...

    《Android:JNI调用C++自定义类的详细方法》源码

    《Android:JNI调用C++自定义类的详细方法》源码,具体参考:https://blog.csdn.net/chaoqiangscu/article/details/83023762

    08_12_JNI_02_jni数据类型&属性方法

    08_12_JNI_02_jni数据类型&属性方法08_12_JNI_02_jni数据类型&属性方法08_12_JNI_02_jni数据类型&属性方法08_12_JNI_02_jni数据类型&属性方法08_12_JNI_02_jni数据类型&属性方法08_12_JNI_02_jni数据类型&属性方法08...

    java源码:JNI代码生成器 JNIGen.zip

    java源码:JNI代码生成器 JNIGen.zip

    JNI调用大全

    Chap1:JNI完全手册... 3 Chap2:JNI-百度百科... 11 Chap 3:javah命令帮助信息... 16 Chap 4:用javah产生一个.h文件... 17 Chap5:jni教程(very very good) 19 Chap6: JNI传递返回值... 26 15.2.2.3 传递字符串... ...

    jni.zip jni编译jni下载

    学习JNI编译时,缺少的jni.h和jni_md.h头文件,Java调用C和C++函数时的JNI使用区别: 注意:jni.h头文件中对于***.c & ***.cpp采用不同的定义

    进程保活(一:JNI层初探):单向循环式启动服务

    技术关键点:开启native子进程,循环间隔的不停去启动下服务,也不判断服务是否die了。而且,如果die了,但是间隔还没到,还是不会启动服务 结论:单杀可以杀死,force close 5.0以上无效,5.0以下部分手机无效,第...

    android studio 下jni学习

    这是一个androidstudio环境下的jni的学习,里面包含了基本数据类型转化,引用数据类型转化,json格式数据类型的转化等

    NDK JNI的学习

    ndk jni的学习

    Android JNI专题文档

    《Android JNI 视频系列>共分为四期: Jni简单demo Jni基本数据类型和方法介绍 Jni解析java自定义数据类型和回调java方法 Jni performance提高和Exception规避

    Java与JNI数据类型对照表

    Java与JNI数据类型对照表,可能有许多不足之处,请大家参考一下。

    android_JNI学习二

    android JNI学习二 的最后实例

    jni-algorithm:jni实现的多数算法

    jni-algorithm 持续更新: jni实现的多个算法 算法1:NativeImageUtils:public static native int[] argbToBitmapColors(byte[] srcData); RGB或者ARGB格式转码成像素点 之后由像素点生成bitmap 转码时间:04-19 15...

    JNI学习二:字符串参数传递与返回值

    jni编写的一个示例,示例中包含一带参数的有返回值的函数。

    android_JNI介绍

    目前Java与Dll交互的技术主要有三种:JNI、JAWIN和JACOB,JNI(Java Native Interface)是SUN提供的Java与系统中的原生方法的技术。JACOB(Java-Com Bridge)提供Java程序调用Microsoft的com队形的方法能力,而除了com...

    JNI技术各类文档

    jni详解 JNI设计实践之路 JNI技术手册 Java_JNI_编程进阶 android_jni操作指南

    Jni 项目 包含各种数据类型转换

    通过jni 用java调用c/c++ 编译的 dll 动态库 帖子地址 https://blog.csdn.net/qq_38777624/article/details/114625668

Global site tag (gtag.js) - Google Analytics