android NDK JNI访问静态成员

文章目录

    • 1.概述
    • 2. 静态成员访问流程
    • 3. java类静态成员JNI访问接口
      • 3.1 类静态成员JNI读访问接口(GetStaticxxxField)
      • 3.1 类静态成员JNI写访问接口(GetStaticxxxField)
    • 4. 类静态成员访问测试
    • 4.1 定义JNI类
      • 4.2 定义JNI 库实现
      • 4.3 标题修改CMakeLists.txt
      • 4.4 测试demo
    • 5. 遇到的问题

1.概述

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

2. 静态成员访问流程

android NDK JNI访问静态成员_第1张图片

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

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

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

android NDK JNI访问静态成员_第2张图片

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

android NDK JNI访问静态成员_第3张图片

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异常。
android NDK JNI访问静态成员_第4张图片

你可能感兴趣的:(JNI,android,ndk,jni,云原生)