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

对于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 jni
09-24 12:32:44.021 19457-19457/com.test.git.jnidemo I/MainActivity-: name修改前: Lucy
09-24 12:32:44.021 19457-19457/com.test.git.jnidemo I/MainActivity-: name修改后: changed Lucy
09-24 12:32:44.021 19457-19457/com.test.git.jnidemo I/MainActivity-: age修改前: 11
09-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修改后: 英语
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值