JNI 中创建对象
在上一篇中介绍了JNI 调用Java中的super.method()。本文是JNI系列的第九篇,介绍JNI中的如何在Native代码中创建Java对象。
系列文章的大纲如下:
- JNI 简介
- JNI 基本类型
- JNI String
- JNI 数组
- JNI 实例变量
- JNI 静态变量
- JNI 回调实例方法与静态方法
- JNI 调用Java中的super.method()
- JNI 中创建对象
- JNI 中创建对象数组
- JNI 中局部引用和全局引用
- JNI 动态注册
- 使用Android NDK编译Android的Native库
JNI 中创建对象
在JNI中创建对象使用如下的一组函数:
// 创建新的对象,调用类clazz的方法ID为methodID的构造方法。
jobject NewObject(JNIEnv *env, jclass clazz, jmethodID methodID, ...);
jobject NewObjectA(JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
jobject NewObjectV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
其中的methodID
需要是通过GetMethodID(clazz, "<init>", sig)
方法获取的。
<init>
是固定的写法,且构造函数返回值都是`void`。
或者使用如下方法创建新的对象:
// 创建新的对象,但不调用构造函数,不对成员进行初始化
jobject AllocObject(JNIEnv *env, jclass clazz);
AllocObject
比较少的使用。
还差一样东西,这个clazz
从哪里来呢?JNI提供一下FindClass
函数来查找需要的类。
// 查找并返回类,类由name指定。
jclass FindClass(JNIEnv *env, const char *name);
假如要查找类java.lang.String
,那么name
就是java/lang/String
;
如果要查找的类为java.lang.Object[]
,那么name
为[Ljava/lang/Object;"
。
有了这两样工具就可以在JNI中创建新的对象了。 通过下面的实例来加深一下理解。
实例
我们来看一个实例。
package myjni;
public class JNIConstructor {
static {
System.loadLibrary("hello");
}
public native Integer getIntegerObject(int number);
public static void main(String[] args) {
JNIConstructor obj = new JNIConstructor();
System.out.println("In Java, the number is " + obj.getIntegerObject(1234));
}
}
如果还不清楚如果生成头文件请参考JNI简介。
生成头文件myjni_JNIConstructor.h
的签名为:
/*
* Class: myjni_JNIConstructor
* Method: getIntegerObject
* Signature: (I)Ljava/lang/Integer;
*/
JNIEXPORT jobject JNICALL Java_myjni_JNIConstructor_getIntegerObject
(JNIEnv *, jobject, jint);
实现函数Java_myjni_JNIConstructor_getIntegerObject
:
#include "myjni_JNIConstructor.h"
#include <iostream>
JNIEXPORT jobject JNICALL Java_myjni_JNIConstructor_getIntegerObject(JNIEnv *env, jobject obj, jint number) {
jclass cls = env->FindClass("java/lang/Integer");
if (cls == nullptr) {
std::cout << "find class java.lang.Integer failed\n";
return nullptr;
}
jmethodID init = env->GetMethodID(cls, "<init>", "(I)V");
if (init == nullptr) {
std::cout << "get constructor failed\n";
return nullptr;
}
jobject integer = env->NewObject(cls, init, number);
jmethodID midToString = env->GetMethodID(cls, "toString", "()Ljava/lang/String;");
if (midToString == nullptr) {
std::cout << "get toString() method failed\n";
return integer;
}
jstring result = (jstring)env->CallObjectMethod(integer, midToString);
const char *resultStr = env->GetStringUTFChars(result, nullptr);
std::cout << "In C++, the number is " << resultStr << "\n";
env->ReleaseStringUTFChars(result, resultStr);
return integer;
}
编译生成动态库,并运行Java程序得到输出:
In Java, the number is 1234
In C++, the number is 1234
vx搜:极客Furzoom,关注获取第一手资料。
本文完。