原文出处:http://www.ccbu.cc/index.php/android/android-jni-object-operate.html
1. 对象操作基本步骤
Jni是沟通Java世界和Native世界的纽带,Java层调用本地方法只用调用Java中定义的本地(native
)方法就可用了,那么,本地的C/C++代码如何调用Java层的代码呢?这就是本章节对象操作
要解决阐述的内容。
一般的,C/C++层要调用Java层代码,需要进行以下步骤。
- 获取Java层对应的
jclass
,通过jclass
来获取Java类的方法,属性。 - 获取Java层对象引用,如果Java层有传引用下来,则可用直接使用,否则就需要在C/C++层调用创建对象的接口来创建Java层对应类的对象。调用Java静态函数不需要对象引用。
- 调用Java层类的静态方法,或者Java层对象的方法。
- 处理返回值。
2. 类操作
2.1 函数列表
Jni中类操作相关的函数包括以下函数:
函数 | 说明 |
---|---|
DefineClass | 从原始类数据的缓冲区中加载类 |
FindClass | 查找类 |
GetSuperclass | 查找父类 |
IsAssignableFrom | 类型判断 |
2.2 关于类名
Jni在加载或查找Java层类时,需要通过类的全名来进行加载,该类的全名为类包含包名的全路径,比如 java.lang.String
类,那么类的全名则为java/lang/String
;
2.3 对应的C++函数定义如下:
/**
* 从原始类数据的缓冲区中加载类
* @param name 类的全名,必须是被UTF-8编码过的字符串。
* @param loader 类加载器
* @param buf 包含 .class 文件数据的缓冲区
* @return java类对象。发生错误时返回NULL
*/
jclass DefineClass(const char *name, jobject loader, const jbyte* buf,
jsize bufLen)
/**
* 查找类
* @param name 类的全名,必须是被UTF-8编码过的字符串。
* @return
*/
jclass FindClass(const char* name)
/**
* 获取父类
* @param clazz Java类对象
* @return java类对象。clazz的父类或NULL
*/
jclass GetSuperclass(jclass clazz)
/**
* 确定clazz1的对象是否可安全地强制转换为clazz2
* @param clazz1 类的对象
* @param clazz2 类的对象
* @return 如果满足以下任一条件,则返回JNI_TRUE:
* 1. 如果clazz1和clazz2是同一个Java类。
* 2. 如果clazz1是clazz2的子类
* 3. 如果clazz1是clazz2接口的实现类
*/
jboolean IsAssignableFrom(jclass clazz1, jclass clazz2)
2.4 对应的C函数定义为:
jclass (*DefineClass)(JNIEnv*, const char*, jobject, const jbyte*, jsize);
jclass (<