JNI获取并修改Java中类的变量和静态变量的值

来源:互联网 发布:企业在淘宝开店 编辑:程序博客网 时间:2024/05/19 18:11

对于JNI的基本使用请移步:Hello JNI

本文主要介绍以下几个函数的使用:

GetObjectClass

GetFieldID,GetStaticFieldID

Get< Type>Field,GetStatic< Type>Field

Set< Type>Field,SetStatic< Type>Field

案例介绍:通过JNI获取并修改Java中类的变量值

本文也是基于上面的代码继续添加:

JniDemo中添加name,age变量,和accessField(),accessStaticField()方法。

public class JniDemo {    //路径:/JNIDemo/app/build/intermediates/classes/debug/com/test/git/jnidemo/JniUtil/JniDemo.class    public String name = "Lucy";    public static int age = 10;    public native String helloJni();    //修改字段值    public native void accessField();    //修改字段值(静态方法)    public native void accessStaticField();    static {        System.loadLibrary("NdkJniDemo");    }}

生成相应的头文件:

JNIEXPORT void JNICALL Java_com_test_git_jnidemo_JniUtil_JniDemo_accessField  (JNIEnv *, jobject);JNIEXPORT void JNICALL Java_com_test_git_jnidemo_JniUtil_JniDemo_accessStaticField  (JNIEnv *, jobject);

JniDemo.cpp

通过JNI获取并修改Java中变量值

对于变量的签名可以参考:JNI类型

JNIEXPORT void JNICALL Java_com_test_git_jnidemo_JniUtil_JniDemo_accessField        (JNIEnv *env, jobject obj){    //1.获取jclass obj是JniDemo对象, JNIDemo.class    jclass cls = (*env).GetObjectClass(obj);    //2.获取jfieldID    //name:属性名称,sig:属性签名    //jfieldID GetFieldID(jclass clazz, const char* name, const char* sig)    jfieldID fid = (*env).GetFieldID(cls, "name", "Ljava/lang/String;");    //3.修改name的值    //a.获取name属性的值 Get<Type>Field    jstring jstr = (jstring) (*env).GetObjectField(obj, fid);    //b.jstring转成c字符串    //isCopy:true复制, false不复制,或者NULL    //const char* GetStringUTFChars(jstring string, jboolean* isCopy)    const char* c_str = (*env).GetStringUTFChars(jstr, JNI_FALSE);    //c.拼接得到新的字符串    char new_char[40] = "changed ";    //复制c_str 到 new_char    strcat(new_char, c_str);    //d.c字符串转换成String    jstring new_jstr = (*env).NewStringUTF(new_char);    //e.修改name值    //Set<Type>Field    (*env).SetObjectField(obj, fid, new_jstr);    //释放资源    (*env).ReleaseStringUTFChars(jstr, c_str);};
通过JNI获取并修改Java中静态变量值
JNIEXPORT void JNICALL Java_com_test_git_jnidemo_JniUtil_JniDemo_accessStaticField        (JNIEnv *env, jobject obj){    //1.获取jclass    jclass cls = env->GetObjectClass(obj);    //2.获取age的jfieldID 注意用GetStaticFieldID方法    jfieldID jfid = env->GetStaticFieldID(cls, "age", "I");    //3.通过jfid获取age的属性值,注意用GetStaticIntField    jint jage = env->GetStaticIntField(cls, jfid);    jage ++;    //4.修改age的属性值,注意用GetStaticIntField    env->SetStaticIntField(cls,jfid, jage);};

MainActivity调用

public class MainActivity extends AppCompatActivity {    private static final String TAG = "MainActivity-";    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        JniDemo jd = new JniDemo();        Log.i(TAG, "helloJni->" + jd.helloJni());        Log.i(TAG, "name修改前: " + jd.name);        jd.accessField();        Log.i(TAG, "name修改后: " + jd.name);        Log.i(TAG, "age修改前: " + jd.age);        jd.accessStaticField();        Log.i(TAG, "age修改后: " + jd.age);    }}

执行结果:

09-24 12:32:44.021 19457-19457/com.test.git.jnidemo I/MainActivity-: helloJni->hello jni09-24 12:32:44.021 19457-19457/com.test.git.jnidemo I/MainActivity-: name修改前: Lucy09-24 12:32:44.021 19457-19457/com.test.git.jnidemo I/MainActivity-: name修改后: changed Lucy09-24 12:32:44.021 19457-19457/com.test.git.jnidemo I/MainActivity-: age修改前: 1109-24 12:32:44.021 19457-19457/com.test.git.jnidemo I/MainActivity-: age修改后: 12

扩展

JNI获取并修改Java中Array的值

JniDemo.class

public String[] courses = {"语文", "数学"};public native void accessArrayField();

com_test_git_jnidemo_JniUtil_JniDemo.h头文件

JNIEXPORT void JNICALL Java_com_test_git_jnidemo_JniUtil_JniDemo_accessArrayField  (JNIEnv *, jobject);

JniDemo.cpp

JNIEXPORT void JNICALL Java_com_test_git_jnidemo_JniUtil_JniDemo_accessArrayField        (JNIEnv *env, jobject jobj){    jclass cls = env->GetObjectClass(jobj);    jfieldID fid = env->GetFieldID(cls, "courses", "[Ljava/lang/String;");    jobjectArray jarray = (jobjectArray) env->GetObjectField(jobj, fid);    env->SetObjectArrayElement(jarray, 0, env->NewStringUTF("英语"));};

MainActivity.java

        Log.i(TAG, "courses修改前: " + jd.courses[0]);        jd.accessArrayField();        Log.i(TAG, "courses修改后: " + jd.courses[0]);

打印结果:

09-24 14:36:23.041 18001-18001/com.test.git.jnidemo I/MainActivity-: courses修改前: 语文09-24 14:36:23.042 18001-18001/com.test.git.jnidemo I/MainActivity-: courses修改后: 英语
0 0
原创粉丝点击