android NDK JNI访问静态成员

本文详细介绍了如何使用JNI从原生代码中访问Java类的静态成员,包括读取和设置静态字段的方法,提供了具体的JNI接口实现示例,并通过一个测试demo展示其工作流程。在实现过程中,注意原生方法不能声明为静态,否则会导致访问静态成员时出现错误。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.概述

  JAVA编程语言支持两种成员,每个实例都有自己的类成员拷贝,然而所有实例共享静态成员。 JNI提供一系列函数支持原生代码获取和设置实例成员和类静态成员。本篇我们来介绍下如何访问类静态成员。

2. 静态成员访问流程

在这里插入图片描述

3. java类静态成员JNI访问接口

3.1 类静态成员JNI读访问接口(GetStaticxxxField)

JNI对不同的类型提供了的访问接口

在这里插入图片描述

3.1 类静态成员JNI写访问接口(GetStaticxxxField)

在这里插入图片描述

4. 类静态成员访问测试

4.1 定义JNI类

我们先定义JNI的接口类,类定义有静态成员,代码如下:

package com.yangyongfeng.JNI_library;

public class StaticFieldAccess {
    private boolean flag;
    public static int sField = 100;
    public static char  my_sex = 'M';
    public  native  void accessStaticField();

    public static void setsField(int sField) {
        StaticFieldAccess.sField = sField;
    }

    public static int getsField() {
        return sField;
    }

    static {
        System.loadLibrary("StaticFieldAccess");
    }
}

4.2 定义JNI 库实现

我们在原生方法里修改类静态成员my_sex值,然后在java类型中打印出来。

//
// Created by Administrator on 2020/12/29 0029.
//

#include "static_field_access.h"
#include <jni.h>
#include <string.h>
#include <stdio.h>

JNIEXPORT void  JNICALL Java_com_yangyongfeng_JNI_1library_StaticFieldAccess_accessStaticField(JNIEnv *env,jobject obj)
{
    jfieldID  fid;
    jint si;
    char type ;
    //get reference to obj's class
    jclass  cls = (*env).GetObjectClass(obj);
    if ( cls == NULL )
        return;
    printf("Run in C:\n");

    //look for the static field si in cls
    //fid = (*env).GetStaticFieldID(cls,"my_sex","C");
    fid = (*env).GetStaticFieldID(cls,"my_sex","C");
    if (fid == NULL){
        return;
    }
    type = (*env).GetStaticCharField(cls,fid);
    printf("StaticFieldIntField.type = %d\n",type);
    (*env).SetStaticCharField(cls,fid,'F');


}

4.3 标题修改CMakeLists.txt

在CMakeLists.txt中增加编译配置,将原生方法static_field_access.cpp编译成动态库StaticFieldAccess.so,配置如下:

add_library( # Specifies the name of the library.

        StaticFieldAccess

        # Sets the library as a shared library.
        SHARED

        # Provides a relative path to your source file(s).
       static_field_access.cpp )

4.4 测试demo

JNI原生库测试代码如下:

 private void StaticFieldAccessTest(){
        Log.d(TAG,this.toString());
        StaticFieldAccess fieldAccess = new StaticFieldAccess();
        Log.d(TAG,Integer.toString(StaticFieldAccess.my_sex));
        Log.d(TAG,"FieldAccess addr:" + fieldAccess.toString());
        fieldAccess.accessStaticField();
        //StaticFieldAccess.accessStaticField();
        Log.d(TAG,"New value: " + StaticFieldAccess.my_sex);


    }

5. 遇到的问题

不能将原生方法定义为静态(static)方法,定义为静态方法后,通过 类名.原生静态方法 调用原生方法时,传递给JNI接口的对象错误,在查找类静态成员是会抛出NoSuchFieldError异常。
在这里插入图片描述

6 代码仓库

完整代码工程仓库

7. 我的公众号

关注我的公众号,分享嵌入式开发,android开发原创文章
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值