本文接着介绍如何在 C/C++ 中访问 Java,主要从以下几个方面来讲述:
- 访问 Java 的成员变量,包括了实例成员和静态成员
- 访问 Java 的方法,包括了成员方法和静态方法
1. Native 访问 Java 成员变量
我们直接看 Demo:
Java 层:
//定义一个被访问的类
public class TestJavaClass {
private String mString = "Hello JNI, this is normal string !";
private static int mStaticInt = 0;
}
//定义两个 native 方法
public native void accessJavaFiled(TestJavaClass testJavaClass);
public native void accessStaticField(TestJavaClass testJavaClass);
c++ 层:
//访问成员变量
extern "C"
JNIEXPORT void JNICALL
Java_com_yuandaima_myjnidemo_MainActivity_accessJavaFiled(JNIEnv *env, jobject thiz,
jobject test_java_class) {
jclass clazz;
jfieldID mString_fieldID;
//获得 TestJavaClass 的 jclass 对象
// jclass 类型是一个局部引用
clazz = env->GetObjectClass(test_java_class);
if (clazz == NULL) {
return;
}
//获得 mString 的 fieldID
mString_fieldID = env->GetFieldID(clazz, "mString", "Ljava/lang/String;");
if (mString_fieldID == NULL) {
return;
}
//获得 mString 的值
jstring j_string = (jstring) env->GetObjectField(test_java_class, mString_fieldID);
//GetStringUTFChars 分配了内存,需要使用 ReleaseStringUTFChars 释放
const char *buf = env->GetStringUTFChars(j_string, NULL);
//修改 mString 的值
char *buf_out = "Hello Java, I am JNI!";
jstring temp = env->NewStringUTF(buf_out);
env->SetObjectField(test_java_class, mString_fieldID, temp);
//jfieldID 不是 JNI 引用类型,不用 DeleteLocalRef
// jfieldID 是一个指针类型,其内存的分配与回收由 JVM 负责,不需要我们去 free
//free(mString_fieldID);
//释放内存
env->ReleaseStringUTFChars(j_string, buf);
//释放局部引用表
env->DeleteLocalRef(j_string);
env->DeleteLocalRef(clazz);
}
//访问静态成员变量
extern "C"
JNIEXPORT void JNICALL
Java_com_yuandaima_myjnidemo_MainActivity_accessStaticField(JNIEnv *env, jobject thiz,
jobject test_java_class) {
jclass clazz;
jfieldID mStaticIntFiledID;
clazz = env->GetObjectClass(test_java_class);
if (clazz == NULL) {
return;
}
mStaticIntFiledID = env->GetStaticFieldID(clazz, "mStaticInt", "I");
//获取静态成员
jint mInt = env->GetStaticIntField(clazz, mStaticIntFiledID);
//修改静态成员
env->SetStaticIntField(clazz, mStaticIntFiledID, 10086);
env->DeleteLocalRef(clazz);
}
访问一个类成员基本分为三部:
- 获取到类对应的 jclass 对象(对应于 Java 层的 Class 对象),jclss 是一个局部引用,使用完后记得使用 DeleteLocalRef 以避免局部引用表溢出。
- 获取到需要访问的类成员的 jfieldID,jfieldID 不是一个 JNI 引用类型,是一个普通指针,指针指向的内存又 JVM 管理,我们无需在使用完后执行 free 清理操作
- 根据被访问对象的类型,使用 GetxxxField 和 SetxxxField 来获得/设置成员变量的值
2. Native 访问 Java 方法
我们直接看 Demo:
Java 层
//等待被 native 层访问的 java 类
public class TestJavaClass {
//......
private void myMethod() {
Log.i("JNI", "this is java myMethod");
}
private static void myStaticMethod() {
Log.d("JNI", "this is Java myStaticMethod");
}
}
//本地方法
public native void accessJavaMethod();
public native void accessStaticMethod();
C++ 层:
extern "C"
JNIEXPORT void JNICALL
Java_com_yuandaima_myjnidemo_MainActivity_accessJavaMethod(JNIEnv *env, jobject thiz) {
//获取 TestJavaClass 对应的 jclass
jclass clazz = env->FindClass("com/yuandaima/myjnidemo/TestJavaClass");
if (clazz == NULL) {
return;
}
//构造函数 id
jmethodID java_construct_method_id = env->GetMethodID(clazz, "<init>", "()V");
if (java_construct_method_id == NULL) {
return;
}
//创建一个对象
jobject object_test = env->NewObject(clazz, java_construct_method_id);
if (object_test == NULL) {
return;
}
//获得 methodid
jmethodID java_method_id = env->GetMethodID(clazz, "myMethod", "()V");
if (java_method_id == NULL) {
return;
}
//调用 myMethod 方法
env->CallVoidMethod(object_test,java_method_id);
//清理临时引用吧
env->DeleteLocalRef(clazz);
env->DeleteLocalRef(object_test);
}
extern "C"
JNIEXPORT void JNICALL
Java_com_yuandaima_myjnidemo_MainActivity_accessStaticMethod(JNIEnv *env, jobject thiz) {
jclass clazz = env->FindClass("com/yuandaima/myjnidemo/TestJavaClass");
if (clazz == NULL) {
return;
}
jmethodID static_method_id = env->GetStaticMethodID(clazz, "myStaticMethod", "()V");
if(NULL == static_method_id)
{
return;
}
env->CallStaticVoidMethod(clazz, static_method_id);
env->DeleteLocalRef(clazz);
}
Native 访问一个 Java 方法基本分为三部:
- 获取到类对应的 jclass 对象(对应于 Java 层的 Class 对象),jclss 是一个局部引用,使用完后记得使用 DeleteLocalRef 以避免局部引用表溢出。
- 获取到需要访问的方法的 jmethodID,jmethodID 不是一个 JNI 引用类型,是一个普通指针,指针指向的内存由 JVM 管理,我们无需在使用完后执行 free 清理操作
- 接着就可以调用 CallxxxMethod/CallStaticxxxMethod 来调用对于的方法,xxx 是方法的返回类型。
参考资料
阅读全文
下载说明:
1、本站所有资源均从互联网上收集整理而来,仅供学习交流之用,因此不包含技术服务请大家谅解!
2、本站不提供任何实质性的付费和支付资源,所有需要积分下载的资源均为网站运营赞助费用或者线下劳务费用!
3、本站所有资源仅用于学习及研究使用,您必须在下载后的24小时内删除所下载资源,切勿用于商业用途,否则由此引发的法律纠纷及连带责任本站和发布者概不承担!
4、本站站内提供的所有可下载资源,本站保证未做任何负面改动(不包含修复bug和完善功能等正面优化或二次开发),但本站不保证资源的准确性、安全性和完整性,用户下载后自行斟酌,我们以交流学习为目的,并不是所有的源码都100%无错或无bug!如有链接无法下载、失效或广告,请联系客服处理!
5、本站资源除标明原创外均来自网络整理,版权归原作者或本站特约原创作者所有,如侵犯到您的合法权益,请立即告知本站,本站将及时予与删除并致以最深的歉意!
6、如果您也有好的资源或教程,您可以投稿发布,成功分享后有站币奖励和额外收入!
7、如果您喜欢该资源,请支持官方正版资源,以得到更好的正版服务!
8、请您认真阅读上述内容,注册本站用户或下载本站资源即您同意上述内容!
原文链接:https://www.dandroid.cn/archives/20404,转载请注明出处。
1、本站所有资源均从互联网上收集整理而来,仅供学习交流之用,因此不包含技术服务请大家谅解!
2、本站不提供任何实质性的付费和支付资源,所有需要积分下载的资源均为网站运营赞助费用或者线下劳务费用!
3、本站所有资源仅用于学习及研究使用,您必须在下载后的24小时内删除所下载资源,切勿用于商业用途,否则由此引发的法律纠纷及连带责任本站和发布者概不承担!
4、本站站内提供的所有可下载资源,本站保证未做任何负面改动(不包含修复bug和完善功能等正面优化或二次开发),但本站不保证资源的准确性、安全性和完整性,用户下载后自行斟酌,我们以交流学习为目的,并不是所有的源码都100%无错或无bug!如有链接无法下载、失效或广告,请联系客服处理!
5、本站资源除标明原创外均来自网络整理,版权归原作者或本站特约原创作者所有,如侵犯到您的合法权益,请立即告知本站,本站将及时予与删除并致以最深的歉意!
6、如果您也有好的资源或教程,您可以投稿发布,成功分享后有站币奖励和额外收入!
7、如果您喜欢该资源,请支持官方正版资源,以得到更好的正版服务!
8、请您认真阅读上述内容,注册本站用户或下载本站资源即您同意上述内容!
原文链接:https://www.dandroid.cn/archives/20404,转载请注明出处。
评论0