一、前言
在NDK编程时,当我们在Java层调用一个原生方法时,不可避免地要涉及到参数的传递,今天,我们就来一起学习一下如何在原生方法中解析从Java层传递过来的数据。
二、参数分类
我们根据Java当中的数据类型,将传递的参数分为以下三类。
2.1 基本数据类型
对于Java,其基本数据类型有八类,这八类基本数据类型在分别和JNI中的jxxx八类基本数据类型相对应,对应关系为:

jni.h和jni_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的子类:
jclass:Class字节码对象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:第二个参数的类型取决于在Java中Native方法的类型:- 如果是一个普通方法,那么参数类型为
jobject,参数含义为调用Native方法的实例。 - 如果是一个
static方法,参数类型为jclass,参数含义为调用Native方法的Class对象。
3.2 引用类型
对于所有的引用类型,JNI将Java中的所有对象当作一个C指针传递到本地方法中,这个指针指向JVM中的内部数据结构,而对于该数据结构的访问需要通过第一个参数JNIEnv*函数表所提供的函数来访问,下面,我们就来介绍这四种类型的基本访问。
3.2.1 字符串
对于字符串,我们可以分为以下几类: **(1) **