您现在的位置是:首页 > 正文

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

2024-04-01 01:12:52阅读 0

对于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修改后: 英语

网站文章

  • 基于单片机的智能宠物监控设计

    基于单片机的智能宠物监控设计

    在本节中宠物管理系统的硬件电路主要包含:供电电路,微处理器最小系统,存储电路,光敏传感器电路,TTL-UART转USB电路,SWD调试及外扩电路接口,按键电路等。此工程项目的开发过程中,熟悉了工程开发...

    2024-04-01 01:12:44
  • ArcGIS批量导出图片

    ArcGIS批量导出图片

    我们在涉及到大量图斑数据或者底图要素需要出图时,就需要借助ArcGIS中的批量出图功能,这样能够减少很多的人力时间。下面是批量导出图斑数据的步骤。所需数据:a.要素数据(矢量的点线面要素数据)b.影像...

    2024-04-01 01:12:36
  • 拼多多的前端面经

    1.说一下vue router的原理 我说了history和hash的原理onhashchange我都说了 原理层说的 他说不对 我整个前后端路由都解释了 他说不对 他问我怎么实现的不刷新 我不知道。2.js、css加载阻塞问题 如果css加载时间长会阻塞后面的渲染吗3.两种图片引用方式? background-image 和 img的区别? 哪个先加载?4.响应式原理...

    2024-04-01 01:12:05
  • 使用MySQL Shell搭建MGR环境

    使用MySQL Shell搭建MGR环境

    更多文章,欢迎关注作者公众号,欢迎一起交流。1)部署 SandBox 环境[root@serverc local]# mysqlshMySQL Shell 8.0.28-commercialCopyr...

    2024-04-01 01:12:01
  • 2022.07.30 Linux矩阵按键驱动笔记1

    这是之前帮客户开发矩阵键盘驱动时记录的笔记。 1. 行GPIO必须为输入,列GPIO必须为输出。 2. 硬件原理图上的引脚与DTS文件中的引脚必须匹配。 3. X30.dts中要配置行,列对应的键值,...

    2024-04-01 01:11:52
  • delphi 判断结构体不为空_数据结构(3)——堆栈的顺序存储实现

    delphi 判断结构体不为空_数据结构(3)——堆栈的顺序存储实现

    堆栈(Stack):顺序存储运算数,需要时倒序输出具有一定操作约束的线性表,只在栈顶做插入删除。插入:入栈删除:出栈后入先出:Last In First Out(LIFO)栈的顺序存储结构通常由一个一...

    2024-04-01 01:11:21
  • docker buildx 构建多平台镜像错误x509: certificate signed by unknown authority

    buildx 构建时,如果去公司内部的仓库拉取镜像时,会遇到下面的这种授权不通过问题。添加到BuildKitd容器中。

    2024-04-01 01:11:15
  • 从"青面兽杨志"护送生辰纲看IT项目管理(不得不转)

    《水浒传》是大家耳熟能详的古典著作之一,我纵然是维吾尔人,但也很早开始接受汉语教育,因此对于该著作也是略知一二。今天这篇文章中,重点讲述下《水浒传》中较为精彩的故事:杨志护送生辰纲前往东京,半路却被晁盖等人劫取。通过这个故事的,可以发现IT团队管理过程中可能出现的若干问题。本篇纯属虚构,若有雷同,那就雷同。开始之前:“青面兽杨志”的出生杨志在《水浒传》中出场是第12回,与刚上梁山不

    2024-04-01 01:10:51
  • 服务器配置vue项目的默认路由,Vue-Router项目设置Nginx伪静态

    Vue-Router项目设置Nginx伪静态使用Vue + Vue-Router的项目,在history模式下,出现了刷新页面404的问题, 服务器为Nginx出现刷新404的原因是Vue-Route...

    2024-04-01 01:10:42
  • ant之build.xml详解

    ant之build.xml详解

    用 Ant 编译 Java 程序,同时产生 javadoc,生成一个 Jar 或 W ar 文件,实现文件的副本

    2024-04-01 01:10:37