日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

jni java共享变量_JNI/NDK开发指南(七)——C/C++访问Java实例变量和静态变量 .

發布時間:2025/4/16 c/c++ 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 jni java共享变量_JNI/NDK开发指南(七)——C/C++访问Java实例变量和静态变量 . 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

在上一章中我們學習到了如何在本地代碼中訪問任意Java類中的靜態方法和實例方法,本章我們也通過一個示例來學習Java中的實例變量和靜態變量,在本地代碼中如何來訪問和修改。靜態變量也稱為類變量(屬性),在所有實例對象中共享同一份數據,可以直接通過【類名.變量名】來訪問。實例變量也稱為成員變量(屬性),每個實例都擁有一份實例變量數據的拷貝,它們之間修改后的數據互不影響。下面看一個例子:

packagecom.study.jnilearn;

publicclassAccessField?{

privatenativestaticvoidaccessInstanceField(ClassField?obj);

privatenativestaticvoidaccessStaticField();

publicstaticvoidmain(String[]?args)?{

ClassField?obj?=newClassField();

obj.setNum(10);

obj.setStr("Hello");

//?本地代碼訪問和修改ClassField為中的靜態屬性num

accessStaticField();

accessInstanceField(obj);

//?輸出本地代碼修改過后的值

System.out.println("In?Java--->ClassField.num?=?"+?obj.getNum());

System.out.println("In?Java--->ClassField.str?=?"+?obj.getStr());

}

static{

System.loadLibrary("AccessField");

}

}

package com.study.jnilearn;

public class AccessField {

private native static void accessInstanceField(ClassField obj);

private native static void accessStaticField();

public static void main(String[] args) {

ClassField obj = new ClassField();

obj.setNum(10);

obj.setStr("Hello");

// 本地代碼訪問和修改ClassField為中的靜態屬性num

accessStaticField();

accessInstanceField(obj);

// 輸出本地代碼修改過后的值

System.out.println("In Java--->ClassField.num = " + obj.getNum());

System.out.println("In Java--->ClassField.str = " + obj.getStr());

}

static {

System.loadLibrary("AccessField");

}

}

AccessField是程序的入口類,定義了兩個native方法:accessInstanceField和accessStaticField,分別用于演示在本地代碼中訪問Java類中的實例變量和靜態變量。其中accessInstaceField方法訪問的是類的實例變量,所以該方法需要一個ClassField實例作為形參,用于訪問該對象中的實例變量。

packagecom.study.jnilearn;

publicclassClassField?{

privatestaticintnum;

privateString?str;

publicintgetNum()?{

returnnum;

}

publicvoidsetNum(intnum)?{

ClassField.num?=?num;

}

publicString?getStr()?{

returnstr;

}

publicvoidsetStr(String?str)?{

this.str?=?str;

}

}

package com.study.jnilearn;

public class ClassField {

private static int num;

private String str;

public int getNum() {

return num;

}

public void setNum(int num) {

ClassField.num = num;

}

public String getStr() {

return str;

}

public void setStr(String str) {

this.str = str;

}

}

在本例中沒有將實例變量和靜態變量定義在程序入口類中,新建了一個ClassField的類來定義類的屬性,目的是為了加深在C/C++代碼中可以訪問任意Java類中的屬性。在這個類中定義了一個int類型的實例變量num,和一個java.lang.String類型的靜態變量str。這兩個變量會被本地代碼訪問和修改。

#include

#ifndef?_Included_com_study_jnilearn_AccessField

#define?_Included_com_study_jnilearn_AccessField

#ifdef?__cplusplus

extern"C"{

#endif

JNIEXPORTvoidJNICALL?Java_com_study_jnilearn_AccessField_accessInstanceField

(JNIEnv?*,?jclass,?jobject);

JNIEXPORTvoidJNICALL?Java_com_study_jnilearn_AccessField_accessStaticField

(JNIEnv?*,?jclass);

#ifdef?__cplusplus

}

#endif

#endif

#include

#ifndef _Included_com_study_jnilearn_AccessField

#define _Included_com_study_jnilearn_AccessField

#ifdef __cplusplus

extern "C" {

#endif

JNIEXPORT void JNICALL Java_com_study_jnilearn_AccessField_accessInstanceField

(JNIEnv *, jclass, jobject);

JNIEXPORT void JNICALL Java_com_study_jnilearn_AccessField_accessStaticField

(JNIEnv *, jclass);

#ifdef __cplusplus

}

#endif

#endif

以上代碼是程序入口類AccessField.class為native方法生成的本地代碼函數原型頭文件

//?AccessField.c

#include?"com_study_jnilearn_AccessField.h"

JNIEXPORTvoidJNICALL?Java_com_study_jnilearn_AccessField_accessInstanceField

(JNIEnv?*env,?jclass?cls,?jobject?obj)

{

jclass?clazz;

jfieldID?fid;

jstring?j_str;

jstring?j_newStr;

constchar*c_str?=?NULL;

//?1.獲取AccessField類的Class引用

clazz?=?(*env)->GetObjectClass(env,obj);

if(clazz?==?NULL)?{

return;

}

//?2.?獲取AccessField類實例變量str的屬性ID

fid?=?(*env)->GetFieldID(env,clazz,"str","Ljava/lang/String;");

if(clazz?==?NULL)?{

return;

}

//?3.?獲取實例變量str的值

j_str?=?(jstring)(*env)->GetObjectField(env,obj,fid);

//?4.?將unicode編碼的java字符串轉換成C風格字符串

c_str?=?(*env)->GetStringUTFChars(env,j_str,NULL);

if(c_str?==?NULL)?{

return;

}

printf("In?C--->ClassField.str?=?%s\n",?c_str);

(*env)->ReleaseStringUTFChars(env,?j_str,?c_str);

//?5.?修改實例變量str的值

j_newStr?=?(*env)->NewStringUTF(env,"This?is?C?String");

if(j_newStr?==?NULL)?{

return;

}

(*env)->SetObjectField(env,?obj,?fid,?j_newStr);

//?6.刪除局部引用

(*env)->DeleteLocalRef(env,?clazz);

(*env)->DeleteLocalRef(env,?j_str);

(*env)->DeleteLocalRef(env,?j_newStr);

}

JNIEXPORTvoidJNICALL?Java_com_study_jnilearn_AccessField_accessStaticField

(JNIEnv?*env,?jclass?cls)

{

jclass?clazz;

jfieldID?fid;

jint?num;

//1.獲取ClassField類的Class引用

clazz?=?(*env)->FindClass(env,"com/study/jnilearn/ClassField");

if(clazz?==?NULL)?{//?錯誤處理

return;

}

//2.獲取ClassField類靜態變量num的屬性ID

fid?=?(*env)->GetStaticFieldID(env,?clazz,"num","I");

if(fid?==?NULL)?{

return;

}

//?3.獲取靜態變量num的值

num?=?(*env)->GetStaticIntField(env,clazz,fid);

printf("In?C--->ClassField.num?=?%d\n",?num);

//?4.修改靜態變量num的值

(*env)->SetStaticIntField(env,?clazz,?fid,?80);

//?刪除屬部引用

(*env)->DeleteLocalRef(env,clazz);

}

// AccessField.c

#include "com_study_jnilearn_AccessField.h"

JNIEXPORT void JNICALL Java_com_study_jnilearn_AccessField_accessInstanceField

(JNIEnv *env, jclass cls, jobject obj)

{

jclass clazz;

jfieldID fid;

jstring j_str;

jstring j_newStr;

const char *c_str = NULL;

// 1.獲取AccessField類的Class引用

clazz = (*env)->GetObjectClass(env,obj);

if (clazz == NULL) {

return;

}

// 2. 獲取AccessField類實例變量str的屬性ID

fid = (*env)->GetFieldID(env,clazz,"str", "Ljava/lang/String;");

if (clazz == NULL) {

return;

}

// 3. 獲取實例變量str的值

j_str = (jstring)(*env)->GetObjectField(env,obj,fid);

// 4. 將unicode編碼的java字符串轉換成C風格字符串

c_str = (*env)->GetStringUTFChars(env,j_str,NULL);

if (c_str == NULL) {

return;

}

printf("In C--->ClassField.str = %s\n", c_str);

(*env)->ReleaseStringUTFChars(env, j_str, c_str);

// 5. 修改實例變量str的值

j_newStr = (*env)->NewStringUTF(env, "This is C String");

if (j_newStr == NULL) {

return;

}

(*env)->SetObjectField(env, obj, fid, j_newStr);

// 6.刪除局部引用

(*env)->DeleteLocalRef(env, clazz);

(*env)->DeleteLocalRef(env, j_str);

(*env)->DeleteLocalRef(env, j_newStr);

}

JNIEXPORT void JNICALL Java_com_study_jnilearn_AccessField_accessStaticField

(JNIEnv *env, jclass cls)

{

jclass clazz;

jfieldID fid;

jint num;

//1.獲取ClassField類的Class引用

clazz = (*env)->FindClass(env,"com/study/jnilearn/ClassField");

if (clazz == NULL) { // 錯誤處理

return;

}

//2.獲取ClassField類靜態變量num的屬性ID

fid = (*env)->GetStaticFieldID(env, clazz, "num", "I");

if (fid == NULL) {

return;

}

// 3.獲取靜態變量num的值

num = (*env)->GetStaticIntField(env,clazz,fid);

printf("In C--->ClassField.num = %d\n", num);

// 4.修改靜態變量num的值

(*env)->SetStaticIntField(env, clazz, fid, 80);

// 刪除屬部引用

(*env)->DeleteLocalRef(env,clazz);

}

以上代碼是對頭文件中函數原型的實現。

運行程序,輸出結果如下:

代碼解析:

一、訪問實例變量

在main方法中,通過調用accessInstanceField()方法來調用本地函數Java_com_study_jnilearn_AccessField_accessInstanceField,定位到函數32行:

j_str?=?(jstring)(*env)->GetObjectField(env,obj,fid);

j_str = (jstring)(*env)->GetObjectField(env,obj,fid);

該函數就是用于獲取ClassField對象中num的值。下面是函數的原型:

jobject?(JNICALL?*GetObjectField)?(JNIEnv?*env,?jobject?obj,?jfieldID?fieldID);

jobject (JNICALL *GetObjectField) (JNIEnv *env, jobject obj, jfieldID fieldID);

因為實例變量str是String類型,屬于引用類型。在JNI中獲取引用類型字段的值,調用GetObjectField函數獲取。同樣的,獲取其它類型字段值的函數還有GetIntField,GetFloatField,GetDoubleField,GetBooleanField等。這些函數有一個共同點,函數參數都是一樣的,只是函數名不同,我們只需學習其中一個函數如何調用即可,依次類推,就自然知道其它函數的使用方法。

GetObjectField函數接受3個參數,env是JNI函數表指針,obj是實例變量所屬的對象,fieldID是變量的ID(也稱為屬性描述符或簽名),和上一章中方法描述符是同一個意思。env和obj參數從Java_com_study_jnilearn_AccessField_accessInstanceField函數形參列表中可以得到,那fieldID怎么獲取呢?了解Java反射的童鞋應該知道,在Java中任何一個類的.class字節碼文件被加載到內存中之后,該class子節碼文件統一使用Class類來表示該類的一個引用(相當于Java中所有類的基類是Object一樣)。然后就可以從該類的Class引用中動態的獲取類中的任意方法和屬性。注意:Class類在Java

SDK繼承體系中是一個獨立的類,沒有繼承自Object。請看下面的例子,通過Java反射機制,動態的獲取一個類的私有實例變量的值:

publicstaticvoidmain(String[]?args)throwsException?{

ClassField?obj?=newClassField();

obj.setStr("YangXin");

//?獲取ClassField字節碼對象的Class引用

Class

分享:

喜歡

0

贈金筆

加載中,請稍候......

評論加載中,請稍候...

發評論

登錄名: 密碼: 找回密碼 注冊記住登錄狀態

昵???稱:

評論并轉載此博文

發評論

以上網友發言只代表其個人觀點,不代表新浪網的觀點或立場。

總結

以上是生活随笔為你收集整理的jni java共享变量_JNI/NDK开发指南(七)——C/C++访问Java实例变量和静态变量 .的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。