NDK 知识梳理(3) JNI 之 Java 和 JNI 数据类型映射

365 阅读3分钟

一、前言

NDK编程时,当我们在Java层调用一个原生方法时,不可避免地要涉及到参数的传递,今天,我们就来一起学习一下如何在原生方法中解析从Java层传递过来的数据。

二、参数分类

我们根据Java当中的数据类型,将传递的参数分为以下三类。

2.1 基本数据类型

对于Java,其基本数据类型有八类,这八类基本数据类型在分别和JNI中的jxxx八类基本数据类型相对应,对应关系为:

通过查看jni.hjni_md.h头文件,会发现jxxx其实是对于C/C++中基本数据类型的宏定义:

# (1) jint
typedef int jint;
# (2) jlong
#ifdef _LP64
typedef long jlong;
#else
typedef long long jlong;
#endif
# (3) jbyte
typedef signed char jbyte;
# (4) jboolean
typedef unsigned char   jboolean;
# (5) jchar
typedef unsigned short  jchar;
# (6) jshort
typedef short           jshort;
# (7) jfloat
typedef float           jfloat;
# (8) jdouble
typedef double          jdouble;

这八类基本数据类型的特点是:我们可以在JNI的原生函数中直接访问。

2.2 引用类型

对于Java当中的引用类型,它们映射到JNI中,都是作为jobject的子类:

  • jclassClass字节码对象
  • jthrowable:异常
  • jstring:字符串
  • jarray:数组,根据数组元素类型的不同,jarray又衍生出九种子类,也就是八种基本数据类型加上引用类型。

它们在jni.h中的定义为:

# (1)
class _jobject {};
# (1)
class _jclass : public _jobject {};
# (2)
class _jthrowable : public _jobject {};
# (3) 
class _jstring : public _jobject {};
# (4)
class _jarray : public _jobject {};
class _jbooleanArray : public _jarray {};
class _jbyteArray : public _jarray {};
class _jcharArray : public _jarray {};
class _jshortArray : public _jarray {};
class _jintArray : public _jarray {};
class _jlongArray : public _jarray {};
class _jfloatArray : public _jarray {};
class _jdoubleArray : public _jarray {};
class _jobjectArray : public _jarray {};

和基本数据类型不同,对于引用类型的访问需要通过JNI提供的方法。

三、实例讲解

下面我们用一个实例来讲解每一种类型的访问方式。

3.1 基本数据类型

从上面的代码可以看出,从Java方法到Native方法,除了前面两个参数,都是一一对应的,前面两个参数的含义为:

  • JNIEnv*:第一个参数是一个指向JVM函数表的指针,函数表中的每一个入口指向一个JNI函数,我们可以通过这些函数去访问JVM中的数据结构。
  • jobject/jclass:第二个参数的类型取决于在JavaNative方法的类型:
  • 如果是一个普通方法,那么参数类型为jobject,参数含义为调用Native方法的实例。
  • 如果是一个static方法,参数类型为jclass,参数含义为调用Native方法的Class对象。

3.2 引用类型

对于所有的引用类型,JNIJava中的所有对象当作一个C指针传递到本地方法中,这个指针指向JVM中的内部数据结构,而对于该数据结构的访问需要通过第一个参数JNIEnv*函数表所提供的函数来访问,下面,我们就来介绍这四种类型的基本访问。

3.2.1 字符串

对于字符串,我们可以分为以下几类: **(1) **

3.2.2 Class 字节码对象

3.2.3 数组

3.2.4 异常