Android JNI 详解

原创 2015年11月20日 10:48:34

JNI的作用

全称是 Java Native Interface (Java本地接口),JNI来自于Java,Android作为一种嵌入式的操作系统,有大量的驱动、硬件相关的功能必须在native层实现,其次C/C++代码的效率也是优于Java的代码,所以一些耗时的计算操作,例如一些加密算法还是应该用JNI开发。
在JNI中 无论是Java到C/C++还是C/C++到Java,中间都没有跨线程的调用,但是在各自的打印线程Id时会得到不同的线程Id,这是因为Java中的线程Id是一个从1开始的整数,而C/C++中则是一个与线程相关的数据结构的指针值。

JNI的用法

  • 装在JNI动态库
    使用JNI时,C/C++的代码是存放在动态库中的,我们需要将动态库加载到进程的内存空间中 装在库是放在System类中的LoadLibrary()方法,原型如下:
public static void loadLibary(String libName)

动态库名称是以lib开头 以.so结尾(在Windows中是.dll) JNI是源于Java中产物,Java为了做到系统之间的兼容,所以将lib 和后缀名省去,譬如说 libmyjni.so 最终传递给loadLibary的参数是myjni

  • 定义native代码
    在Java中使用JNI方法需要在方法前加上native关键字
private static native void init()
  • 编写JNI动态库
    JNI动态库中有一个方法叫做 “JNI_OnLoader”的函数,这个函数会在动态库被加载后由系统调用,用于完成JNI函数的注册,这样做的目的是使得Java中的native方法能够找到JNI动态库中的对应的C的函数。

  • 参数签名
    参数的签名的作用是代表数据类型,在Java中的数据类型与JNI中都有相应的表示方法

参数签名 Java类型 JNI类型
Z boolean jboolean
C char jchar
B byte jbyte
S short jshort
I int jint
J long jlong
F float jboolean
D double jdouble
[Z boolean[] jbooleanArray
[C char[] jcharArray
[B byte[] jbyteArray
[S short[] jshortArray
[I int[] jintArray
[J long[] jlongArray
[F float[] jbooleanArray
[D double[] jdoubleArray

注:复杂类型的签名格式 ‘L’加上“全限定类名” 再加上“; ” 例如Java中的String 的参数签名应该是
L/java/lang/String;
注:有关数组相关的操作
JNI中的数组类型 例如jbyteArray、jcharArray其实只是jobject通过typedef定义出来的别名。在JNIEnv中也定义了与数组相关的操作函数
- 获取数组元素的个数
jsize GetArrayLength(jarray array)
- 将JNI数组类型转换为基本数组类型(每种基本类型都有自己的转换)
jint* GetIntArrayElements(jintArray array, jint* elems, Jint mode)
- 回收数组的内存
void ReleaseIntArrayElements(jintArray array, jint * elems, jint mode)
注:有关字符串的相关操作
- 获取字符串的长度
jsize GetStringUTFLength(jstring string)
- 转换成UTF-8
const char* GetStringUTFChars(jstring string, jboolean* iscopy)
- 转换成Unicode的字符串
const jchar* GetStringChars(jstring string, jboolean* iscopy)

在C/C++ 中调用Java

  • 创建一个Java对象
jobject NewObject(jclass clazz, jmethodID methodID, ...)

参数claszz是指Java对象(不是类的实例对象),可以通过函数FindClass()获得;
参数methodID 是构造函数
FindClass()的原型是:

jclass FindClass(const* char)

例如String类的传入参数就是 “/java/lang/String”
在调用一个Java对象的方法或对Java中的域变量进行操作时,首先需要获取这个方法或者变量Id。可以用以下方法获取:

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

注: 如果是获得构造函数在name 的传入参数必须是 “ < init > ”

jfield GetFieldID(jclass clazz, const char* name, const char* sig)
  • 调用Java类的方法
    JNI环境JNIENv提供了多种调用Java类中的方法
    JNI提供了针对不同返回值的函数:
jchar CallCharMethod(jobject object, jmethodID methodID, ...)
jboolean CallBooleanMethod(jobject object, jmethodID methodID, ...)
jint CallIntMethod(jobject object, jmethodID methodID, ...)
jbyte CallByteMethod(jobject object, jmethodID methodID, ...)
jshort CallShortMethod(jobject object, jmethodID methodID, ...)
jlong CallLongMethod(jobject object, jmethodID methodID, ...)
jdouble CallDoubleMethod(jobject object, jmethodID methodID, ...)
jobject CallObjectMethod(jobject object, jmethodID methodID, ...)
void CallVoidMethod(jobject object, jmethodID methodID, ...)

如果是调用的静态方法只需要Java类中的对象就可以了不需要实例对象,并且在每条函数前面多了一个static 字样:

jchar CallStaticCharMethod(jobject object, jmethodID methodID, ...)
jboolean CallStaticBooleanMethod(jobject object, jmethodID methodID, ...)
jint CallStaticIntMethod(jobject object, jmethodID methodID, ...)
jbyte CallStaticByteMethod(jobject object, jmethodID methodID, ...)
jshort CallStaticShortMethod(jobject object, jmethodID methodID, ...)
jlong CallStaticLongMethod(jobject object, jmethodID methodID, ...)
jdouble CallStaticDoubleMethod(jobject object, jmethodID methodID, ...)
jobject CallStaticObjectMethod(jobject object, jmethodID methodID, ...)
void CallStaticVoidMethod(jobject object, jmethodID methodID, ...)
  • 存取Java类的域变量
    JNIEnv定义了一组函数 可以对Java对象中的域变量进行存取,根据基本类型的不同以及静态与非静态的不同,对应有不同的函数:

获取非静态变量对应的一系列函数

jobject GetObjectField(jobject obj, jfieldID fieldID)
jboolean GetBooleanField(jobject obj, jfieldID fieldID)
jbyted GetByteField(jobject obj, jfieldID fieldID)
jchar GetCharField(jobject obj, jfieldID fieldID)
jshort GetShortField(jobject obj, jfieldID fieldID)
jint GetIntField(jobject obj, jfieldID fieldID)
jlong GetLongField(jobject obj, jfieldID fieldID)
jfloat GetFloatField(jobject obj, jfieldID fieldID)
jdouble GetDoubleField(jobject obj, jfieldID fieldID)

获取静态变量对应的一系列函数

jobject GetStaticObjectField(jobject obj, jfieldID fieldID)
jboolean GetStaticBooleanField(jobject obj, jfieldID fieldID)
jbyted GetStaticByteField(jobject obj, jfieldID fieldID)
jchar GetStaticCharField(jobject obj, jfieldID fieldID)
jshort GetStaticShortField(jobject obj, jfieldID fieldID)
jint GetStaticIntField(jobject obj, jfieldID fieldID)
jlong GetStaticLongField(jobject obj, jfieldID fieldID)
jfloat GetStaticFloatField(jobject obj, jfieldID fieldID)
jdouble GetStaticDoubleField(jobject obj, jfieldID fieldID)

设置非静态成员变量

void SetObjectField(jobject obj, jfieldID fieldID, jobject value)
void SetBooleantField(jobject obj, jfieldID fieldID, jboolean value)
void SetByteField(jobject obj, jfieldID fieldID, jbyte value)
void SetCharField(jobject obj, jfieldID fieldID, jchar value)
void SetShortField(jobject obj, jfieldID fieldID, jshort value)
void SetIntField(jobject obj, jfieldID fieldID, jint value)
void SetLongField(jobject obj, jfieldID fieldID, jlong value)
void SetFloatField(jobject obj, jfieldID fieldID, jfloat value)
void SetDoubleField(jobject obj, jfieldID fieldID, jdouble value)

设置静态成员变量

void SetStaticObjectField(jobject obj, jfieldID fieldID, jobject value)
void SetStaticBooleantField(jobject obj, jfieldID fieldID, jboolean value)
void SetStaticByteField(jobject obj, jfieldID fieldID, jbyte value)
void SetStaticCharField(jobject obj, jfieldID fieldID, jchar value)
void SetStaticShortField(jobject obj, jfieldID fieldID, jshort value)
void SetStaticIntField(jobject obj, jfieldID fieldID, jint value)
void SetStaticLongField(jobject obj, jfieldID fieldID, jlong value)
void SetStaticFloatField(jobject obj, jfieldID fieldID, jfloat value)
void SetStaticDoubleField(jobject obj, jfieldID fieldID, jdouble value)
版权声明:本文为博主原创文章,未经博主允许不得转载。

android系统JNI编程详解

  • 2017年03月26日 21:53
  • 516KB
  • 下载

Android开发书籍 - JNI详解_导航版

  • 2014年04月21日 19:08
  • 541KB
  • 下载

Android JNI 使用的数据结构JNINativeMethod详解

Andoird 中使用了一种不同传统Java JNI的方式来定义其native的函数。其中很重要的区别是Andorid使用了一种Java 和 C 函数的映射表数组,并在其中描述了函数的参数和返回值。这...

Android下JNI入门详解

  • 2011年03月15日 18:22
  • 211KB
  • 下载

Android深入研究JNI详解

Java Native Interface (JNI)标准是 java 平台的一部分,它允许 Java 代码和其他语言写的代码进行 交互。JNI 是本地编程接口,它使得在 Java 虚拟机 (VM)...

Android JNI作用及其详解

Java Native Interface (JNI)标准是Java平台的一部分,它允许Java代码和其他语言写的代码进行交互。JNI 是本地编程接口,它使得在 Java 虚拟机 (VM) 内部运行的...

Android平台Native开发与JNI机制详解

JNI的出现使得开发者既可以利用Java语言跨平台、类库丰 富、开发便捷等特点,又可以利用Native语言的高效。 JNI是JVM实现中的一部分,因此Native语言和Java代码都运行在J...

Android的NDK开发(3)————JNI数据类型的详解

/********************************************************************************************  * au...
  • neng18
  • neng18
  • 2014年07月10日 11:12
  • 388

Android JNI 使用的数据结构JNINativeMethod详解

最近在做关于Android语音识别的东东。研究Recognizer源码的时候碰到个关于JNINativeMethod的结构体,不解,Google之在网上找到了片文章,见文后。结构体代码如下: ...

Android的NDK开发(3)————JNI数据类型的详解

from: http://blog.csdn.net/conowen/article/details/7523145 /*******************************...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Android JNI 详解
举报原因:
原因补充:

(最多只允许输入30个字)