JNI开发之访问java对象非静态属性和静态属性

本文介绍如何使用JNI访问Java中的非静态与静态属性,并通过示例演示如何在C代码中读取和修改这些属性。

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

前言:在上一篇博客中介绍了jni的基本数据类型,本博客就要介绍些j访问ava对象的非静态属性和静态属性!

-----------分割线----------

我们先来看下对象的类型:


再来看一下java签名 每个java属性方法都有其对应的属性签名


上面的表只有一部分签名,如果发现你的方法没有签名需要自己在dos下查看:打开dos窗口 打开工程木…./src/bin/目录下 然后输入javap -s -p 包名.类名

---------------分割线------------

访问非静态属性通过jni更改属性的值:

java代码:

package com.fly;

public class TestJni {

	// 创建一个非静态属性
	String str = "hello";

	public static void main(String[] args) {

		TestJni tj = new TestJni();
		System.out.println("--C没修改前:-->>" + tj.str);
		// 进入c去修改
		tj.jniCall();
		System.out.println("--C没修改后:-->>" + tj.str);
	}

	// 访问java静态属性并且修改为 hello world
	public native void jniCall();

	// 加载动态库
	static {
		System.loadLibrary("JNI");
	}
}
然后查找属性签名:


c头文件.h中:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include "jni.h"
/* Header for class com_fly_TestJni */
#ifndef _Included_com_fly_TestJni
#define _Included_com_fly_TestJni
#ifdef __cplusplus
extern "C" {
#endif

	/*
	* Class:     com_fly_TestJni
	* Method:    getCStringStatic
	* Signature: ()Ljava/lang/String;
	*/
	//非静态的
	JNIEXPORT jint JNICALL Java_com_fly_TestJni_jniCall
		(JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

c源文件代码中:

#include"com_fly_TestJni.h" 

JNIEXPORT jint JNICALL Java_com_fly_TestJni_jniCall
(JNIEnv *env, jobject jobj){
	//获取jonj的class本例当中就是DemoJniBaseType的class对象
	jclass cls = (*env)->GetObjectClass(env, jobj);

	// 函数原型:jfieldID (JNICALL *GetFieldID)(JNIEnv *env, jclass clazz, const char *name, const char *sig);
	// 第一个参数 不需要解释 
	// 第二个参数 属性所在对象的class本例当中就是TestJni的class对象
	// 第三个参数 属性变量名字
	// 第四个参数 属性签名
	// 返回属性变量的id 在用id得到变量引用
	jfieldID file_id = (*env)->GetFieldID(env, cls, "str", "Ljava/lang/String;");

	//函数原型:jobject (JNICALL *GetObjectField)(JNIEnv *env, jobject obj, jfieldID fieldID);
	//第一个参数 ..
	//第二个参数 属性id
	//返回 属性变量引用
	jstring string = (*env)->GetObjectField(env, jobj, file_id);

	//函数原型:const char* (JNICALL *GetStringUTFChars)(JNIEnv *env, jstring str, jboolean *isCopy);
	//第一个参数...
	//第二个参数 属性变量引用
	//第三个参数 建议传入NULL  特别强调:调用此方法时内部会决定是否拷贝java属性变量的指针引用
	// 如果拷贝了那么第三个参数 字面量就是true 反知
	char * cchar = (*env)->GetStringUTFChars(env, string, NULL);

	//printf("得到来自java的字符串%s",cchar);

	////jstring(JNICALL *NewStringUTF)
	//  //(JNIEnv *env, const char *utf);
	jstring newjstring = (*env)->NewStringUTF(env, "hello world");


	//函数原型:void (JNICALL *SetObjectField)(JNIEnv *env, jobject obj, jfieldID fieldID, jobject val);
	//第一个参数
	//第二个参数 属性所在对象
	//第三个参数 属性id
	//第四个参数 赋值
	//设置对象属性数值
	(*env)->SetObjectField(env, jobj, file_id, newjstring);

	//释放GetStringUTFChars 所拷贝java变量引用 
	//在取得字符串后,当已经不再之用,需要通过ReleaseStringChars、ReleaseStringUTFChars来释放拷贝所用的内存或释放Java的String对象的引用
	(*env)->ReleaseStringChars(env, string, cchar);
}
最后生成dll文件复制到java项目的更目录中,运行:


--------分割线--------

访问静态属性通过jni更改属性的值:

java代码:

package com.fly;

public class TestJni {

	// 创建一个静态属性
	public static String str = "static hello";
	public native static void callStaticStr();
	public static void main(String[] args) {
		callStaticStr();
		System.out.println(str);
	}

	// 加载动态库
	static {
		System.loadLibrary("JNI");
	}
}
C代码
#include"com_fly_TestJni.h" 

JNIEXPORT jint JNICALL Java_com_fly_TestJni_callStaticStr
(JNIEnv *env, jclass jcs){
	//函数原型:jfieldID(JNICALL *GetStaticFieldID)(JNIEnv *env, jclass clazz, const char *name, const char *sig);
	//第一个参数 
	//第二个参数 静态属性对应类的class
	//第三个参数 静态属性名字
	//第四个参数 属性签名
	//返回 属性id
	jfieldID field = (*env)->GetStaticFieldID(env, jcs, "str", "Ljava/lang/String;");

	//函数原型jobject(JNICALL *GetStaticObjectField)(JNIEnv *env, jclass clazz, jfieldID fieldID);
	//第一个参数
	//第二个参数 对应静态变量对应类的class
	//第三个参数 静态属性的id
	//返回对应object属性
	jstring fields = (*env)->GetStaticObjectField(env, jcs, field);

	printf("come from java string%s", (*env)->GetStringUTFChars(env, fields, NULL));

	jstring restring = (*env)->NewStringUTF(env, "static hello world");
	//函数原型void (JNICALL *SetStaticObjectField)(JNIEnv *env, jclass clazz, jfieldID fieldID, jobject value);

	(*env)->SetStaticObjectField(env, jcs, field, restring);
}
运行:


--------完---------


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

等待着冬天的风

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值