本文主要说明了在Android应用程序中,怎么使用jni交互. 包括:回调接口,获取对象,不同线程汇总怎么使用JNIEnv *env等实例.
简单的理解一下概念
在jni中,用jfieldID和jmethodID来表示Java类的成员变量和成员函数.
比如:我们的jni侧要获取java对象中的某个String. java代码精简如下:
class InstanceFieldAccess {
private String text;
private native void accessField();
public static void main(String args[]) {
InstanceFieldAccess ifa = new InstanceFieldAccess();
ifa.text = "abcdefg";
ifa.accessField();
System.out.println("Java output");
System.out.println(" ifa.text = \"" + ifa.text + "\"");
}
static {
System.loadLibrary("InstanceFieldAccess");
}
}
c++代码精简如下:
JNIEXPORT void JNICALL Java_InstanceFieldAccess_accessField(JNIEnv *env, jobject obj)
{
jfieldID fid;
jstring jstr;
const char *str;
jclass cls = (*env)->GetObjectClass(env, obj);
printf("C output:\n");
fid = (*env)->GetFieldID(env, cls, "text", "Ljava/lang/String;");
if (fid == NULL) {
return;
}
jstr = (*env)->GetObjectField(env, obj, fid);
str = (*env)->GetStringUTFChars(env, jstr, NULL);
if (str == NULL) {
return;
}
printf(" c.s = \"%s\"\n", str);
(*env)->ReleaseStringUTFChars(env, jstr, str);
jstr = (*env)->NewStringUTF(env, "123");
if (jstr == NULL) {
return;
}
(*env)->SetObjectField(env, obj, fid, jstr);
}
Android的java文件怎么写
public interface IWifiStaServiceService {
public ActivateOutput activate();
public AddApOutput addAp(WifiConfiguration wifiConfiguration);
public ConnectOutput connect(WifiConfiguration wifiConfiguration);
public DeactivateOutput deactivate();
public DisconnectOutput disconnect();
public ForgetOutput forget(WifiApID wifiApID);
public GetApListOutput getApList();
public GetConfiguredApListOutput getConfiguredApList();
public GetConnectedApOutput getConnectedAp();
public GetConnectionInfoOutput getConnectionInfo();
public GetMacAddressOutput getMacAddress();
public IsActivatedOutput isActivated();
public ScanOutput scan();
public UpdateApOutput updateAp(WifiConfiguration wifiConfiguration);
}
public class WifiStaServiceServiceStub {
public static final String LOG_TAG = "WifiStaServiceServiceStub";
public static final String INSTANCE_NAME_1 = "WifiStaService_Provider/WifiStaService_ProviderRootSwc/WifiStaService1";
private static final int METHOD_ACTIVATE = 0;
private static final int METHOD_ADDAP = 1;
private static final int METHOD_CONNECT = 2;
private static final int METHOD_DEACTIVATE = 3;
private static final int METHOD_DISCONNECT = 4;
private static final int METHOD_FORGET = 5;
private static final int METHOD_GETAPLIST = 6;
private static final int METHOD_GETCONFIGUREDAPLIST = 7;
private static final int METHOD_GETCONNECTEDAP = 8;
private static final int METHOD_GETCONNECTIONINFO = 9;
private static final int METHOD_GETMACADDRESS = 10;
private static final int METHOD_ISACTIVATED = 11;
private static final int METHOD_SCAN = 12;
private static final int METHOD_UPDATEAP = 13;
private static IWifiStaServiceService mService;
private static native void native_init(String ap_env);
private static native void native_setup(Object object, String instance);
private static native void native_finalize();
private static native void native_sendService();
private static native void native_stopSendService();
private static native void native_notifyRssiChanged(byte[] data);
private static native void native_notifyScanFinished(byte[] data);
private static native void native_notifyStaConnChanged(byte[] data);
private static native void native_notifyStationChanged(byte[] data);
static {
try {
System.loadLibrary("wifistaservice");
Log.d(LOG_TAG, "load wifistaservice");
} catch (Exception ex) {
Log.e(LOG_TAG, "System.loadLibrary Exception " + ex);
} catch (Error err) {
Log.e(LOG_TAG, "System.loadLibrary Error " + err);
}
}
public WifiStaServiceServiceStub(IWifiStaServiceService service, String instance, String ap_env) {
Log.d(LOG_TAG, "new WifiStaServiceServiceStub");
native_init(ap_env);
mService = service;
native_setup(new WeakReference<WifiStaServiceServiceStub>(this), instance);
}
protected void finalize() {
native_finalize();
}
public void sendService() {
native_sendService();
}
public void stopSendService() {
native_stopSendService();
}
public void notifyRssiChanged(WifiAp rssiChanged) {
Log.d(LOG_TAG, "native_notifyRssiChanged");
native_notifyRssiChanged(rssiChanged.toByteArray());
}
public void notifyScanFinished(WifiApList scanFinished) {
Log.d(LOG_TAG, "native_notifyScanFinished");
native_notifyScanFinished(scanFinished.toByteArray());
}
public void notifyStaConnChanged(WifiAp staConnChanged) {
Log.d(LOG_TAG, "native_notifyStaConnChanged");
native_notifyStaConnChanged(staConnChanged.toByteArray());
}
public void notifyStationChanged(int stationChanged) {
Log.d(LOG_TAG, "native_notifyStationChanged");
WifiStaServiceProto.ProtoUint8 proto_stationChanged = new WifiStaServiceProto.ProtoUint8();
proto_stationChanged.value = stationChanged;
native_notifyStationChanged(proto_stationChanged.toByteArray(proto_stationChanged));
}
private static byte[] postEventFromNative(Object Control_ref, int what, byte[] obj) {
final WifiStaServiceServiceStub serviceimpl = (WifiStaServiceServiceStub)((WeakReference)Control_ref).get();
if (serviceimpl == null) {
Log.e(LOG_TAG, "postEventFromNative error : service is null");
return null;
}
Log.d(LOG_TAG, "postEventFromNative what= " + what + " obj= " + obj);
switch (what) {
case METHOD_ACTIVATE:
ActivateOutput ret_activate = mService.activate();
if (ret_activate != null) {
return ret_activate.toByteArray();
}
break;
case METHOD_ADDAP:
if (obj != null) {
try {
WifiStaServiceProto.AddApInput in_addAp = WifiStaServiceProto.AddApInput.parseFrom(obj);
AddApOutput ret_addAp = mService.addAp(WifiConfiguration.fromByteArray(WifiStaServiceProto.WifiConfiguration.toByteArray(in_addAp.wifiConfiguration)));
if (ret_addAp != null) {
Log.d(LOG_TAG, "AddApOutput is not null ");
return ret_addAp.toByteArray();
} else {
Log.d(LOG_TAG, "AddApOutput is null ");
}
} catch (com.google.protobuf.nano.InvalidProtocolBufferNanoException e) {
Log.d(LOG_TAG, e.toString());
}
}
break;
case METHOD_CONNECT:
if (obj != null) {
try {
WifiStaServiceProto.ConnectInput in_connect = WifiStaServiceProto.ConnectInput.parseFrom(obj);
ConnectOutput ret_connect = mService.connect(WifiConfiguration.fromByteArray(WifiStaServiceProto.WifiConfiguration.toByteArray(in_connect.wifiConfiguration)));
if (ret_connect != null) {
Log.d(LOG_TAG, "ConnectOutput is not null ");
return ret_connect.toByteArray();
} else {
Log.d(LOG_TAG, "ConnectOutput is null ");
}
} catch (com.google.protobuf.nano.InvalidProtocolBufferNanoException e) {
Log.d(LOG_TAG, e.toString());
}
}
break;
default:
break;
}
return null;
}
}
jni头文件的定义
头文件定义了java代码对应的native方法,以及一个回调类.主要是用来回调java侧代码的postEventFromNative方法.
#ifndef _Included_com_yf_soa_wifistaservice_WifiStaServiceNativeListener
#define _Included_com_yf_soa_wifistaservice_WifiStaServiceNativeListener
#include <jni.h>
#include "WifiStaServiceNativeListener.h"
#include "wifistaservice/wifistaservice_skeleton.h"
#ifdef __cplusplus
extern "C" {
#endif
namespace yf {
namespace soa {
struct fields_t {
jfieldID context;
jmethodID post_event;
};
JNIEXPORT void JNICALL Java_com_yf_soa_wifistaservice_WifiStaServiceServiceStub_native_1init
(JNIEnv *, jclass, jstring);
JNIEXPORT void JNICALL Java_com_yf_soa_wifistaservice_WifiStaServiceServiceStub_native_1setup
(JNIEnv *, jclass, jobject, jstring);
JNIEXPORT void JNICALL Java_com_yf_soa_wifistaservice_WifiStaServiceServiceStub_native_1finalize
(JNIEnv *, jclass);
JNIEXPORT void JNICALL Java_com_yf_soa_wifistaservice_WifiStaServiceServiceStub_native_1offerService
(JNIEnv *, jclass);
JNIEXPORT void JNICALL Java_com_yf_soa_wifistaservice_WifiStaServiceServiceStub_native_1stopOfferService
(JNIEnv *, jclass);
JNIEXPORT void JNICALL Java_com_yf_soa_wifistaservice_WifiStaServiceServiceStub_native_1notifyRssiChanged
(JNIEnv *, jclass, jbyteArray);
JNIEXPORT void JNICALL Java_com_yf_soa_wifistaservice_WifiStaServiceServiceStub_native_1notifyScanFinished
(JNIEnv *, jclass, jbyteArray);
JNIEXPORT void JNICALL Java_com_yf_soa_wifistaservice_WifiStaServiceServiceStub_native_1notifyStaConnChanged
(JNIEnv *, jclass, jbyteArray);
JNIEXPORT void JNICALL Java_com_yf_soa_wifistaservice_WifiStaServiceServiceStub_native_1notifyStationChanged
(JNIEnv *, jclass, jbyteArray);
class WifiStaServiceNativeListenerImpl: public WifiStaServiceNativeListener {
public:
WifiStaServiceNativeListenerImpl(JNIEnv* env, jobject thiz, jobject weak_thiz);
~WifiStaServiceNativeListenerImpl();
virtual void syncDetachCurrentThread();
virtual jbyteArray notify(JNIEnv *env, int msg, const jbyteArray obj);
private:
jclass mClass;
jobject mObject;
};
class WifiStaServiceNative : public yf::platform::WifiStaServiceSkeleton {
public:
virtual ~WifiStaServiceNative();
static WifiStaServiceNative& instantiate() {
static WifiStaServiceNative elmn;
return elmn;
}
virtual void registerListener(const std::shared_ptr<WifiStaServiceNativeListener> listener);
virtual sovpap::core::Future<nm_wifistaservice::internal::methods::Activate::Output> Activate();
virtual sovpap::core::Future<nm_wifistaservice::internal::methods::AddAp::Output> AddAp(const DataTypes::WifiConfiguration& wifiConfiguration);
virtual sovpap::core::Future<nm_wifistaservice::internal::methods::Connect::Output> Connect(const DataTypes::WifiConfiguration& wifiConfiguration);
void notifyRssiChanged(const DataTypes::WifiAp& rssiChanged);
void notifyScanFinished(const DataTypes::WifiApList& scanFinished);
void notifyStaConnChanged(const DataTypes::WifiAp& staConnChanged);
void notifyStationChanged(const DataTypes::StationState_ref& stationChanged);
private:
explicit WifiStaServiceNative();
WifiStaServiceNative& operator = (const WifiStaServiceNative&)=delete;
std::shared_ptr<WifiStaServiceNativeListener> m_listener;
enum notifyType {
METHOD_ACTIVATE,
METHOD_ADDAP,
METHOD_CONNECT
};
};
}
}
#ifdef __cplusplus
}
#endif
#endif
看一下另一个回调函数的头文件
#ifndef WIFISTASERVICENATIVELISTENER_H
#define WIFISTASERVICENATIVELISTENER_H
#include <jni.h>
using namespace android;
#ifndef __cplusplus
# error ERROR: This file requires C++ compilation (use a .cpp suffix)
#endif
namespace yf {
namespace soa {
class WifiStaServiceNativeListener
{
public:
virtual void syncDetachCurrentThread() = 0;
virtual jbyteArray notify(JNIEnv *env, int msg, const jbyteArray obj) = 0;
virtual ~WifiStaServiceNativeListener(){};
};
}
}
#endif
再理解几个概念
JavaVM是虚拟机在JNI中的表示,一个JVM中只有一个JavaVM对象,这个对象是线程共享的。
通过JNIEnv我们可以获取一个Java虚拟机对象,其函数如下:
jint GetJavaVM(JNIEnv *env, JavaVM **vm);
- vm:用来存放获得的虚拟机的指针的指针。
- return:成功返回0,失败返回其他。
AttachCurrentThread 链接到虚拟机
JNIEnv指针仅在创建它的线程有效。如果我们需要在其他线程访问JVM,那么必须先调用AttachCurrentThread 将当前线程与JVM进行关联,然后才能获得JNIEnv对象。当然,我们在必要时需要调用DetachCurrentThread 来解除链接。
jint AttachCurrentThread(JavaVM* vm , JNIEnv** env , JavaVMAttachArgs* args);
- vm:虚拟机对象指针。
- env:用来保存得到的JNIEnv的指针。
- args:链接参数,参数结构体如下所示。
- return:链接成功返回0,连接失败返回其他。
仔细看看jni的实现文件
#include <jni.h>
#include <android/log.h>
#include <utils/Log.h>
#include <utils/Mutex.h>
#include "WifiStaServiceServiceJni.h"
#include <WifiStaServiceDataTransfer.h>
#include "ara/core/promise.h"
#include "ara/core/initialization.h"
#ifdef LOG_TAG
#undef LOG_TAG
#endif
#define LOG_TAG "WifiStaServiceServiceJni"
#ifdef __cplusplus
extern "C" {
#endif
namespace yf {
namespace soa {
std::string g_instance_name;
static fields_t fields;
static pthread_key_t sThreadKey;
static JavaVM* javaVM;
static android::Mutex sJNIEnvLock;
jobject g_WifiStaServiceServiceStubClass;
static JNIEnv *getJNIEnv() {
android::Mutex::Autolock l(sJNIEnvLock);
ALOGD("[%s:%d][%s]", __FUNCTION__, __LINE__, __FILE__);
if (javaVM == NULL) {
ALOGE("[%s:%d][%s] Java VM is NULL", __FUNCTION__, __LINE__, __FILE__);
return NULL;
}
JNIEnv *envnow = NULL;
int status = javaVM->GetEnv((void **)&envnow, JNI_VERSION_1_6);
ALOGD("[%s:%d][%s] GetEnv::status = [%d]", __FUNCTION__, __LINE__, __FILE__, status);
if (status == JNI_EDETACHED) {
if( 0 <= javaVM->AttachCurrentThread(&envnow, NULL)) {
ALOGD("[%s:%d][%s] AttachCurrentThread::status = [%d]", __FUNCTION__, __LINE__, __FILE__, status);
if (NULL == pthread_getspecific(sThreadKey)) {
pthread_setspecific(sThreadKey, &envnow);
}
}
}
return envnow;
}
JNIEXPORT void JNICALL Java_com_yf_soa_wifistaservice_WifiStaServiceServiceStub_native_1init
(JNIEnv * env, jclass clazz, jstring ap_env) {
ALOGD("=================== JNI call native_init ========================");
jclass jcls = env->FindClass("com/yf/soa/wifistaservice/WifiStaServiceServiceStub");
g_WifiStaServiceServiceStubClass = env->NewGlobalRef(jcls);
fields.post_event = env->GetStaticMethodID(jcls, "postEventFromNative", "(Ljava/lang/Object;I[B)[B");
env->GetJavaVM(&javaVM);
if (fields.post_event == NULL) {
ALOGD("JNI_native_init fields.post_event is null");
return;
}
if (getenv("AA_CONFIG_FILES_PATH")) {
ALOGD("env already setted, AA_CONFIG_FILES_PATH: %s", getenv("AA_CONFIG_FILES_PATH"));
} else {
if (ap_env) {
const char *jap_env = env->GetStringUTFChars(ap_env, NULL);
if (0 != setenv("AA_CONFIG_FILES_PATH", jap_env, 1)) {
ALOGE("setenv error ");
}
if (!ara::core::Initialize().HasValue()) {
ALOGE("ara::core::init error ");
ara::core::Abort("ara::core::Initialize() failed for Service, calling abort...");
}
} else {
ALOGE("native_init without ap env set up");
}
}
}
JNIEXPORT void JNICALL Java_com_yf_soa_wifistaservice_WifiStaServiceServiceStub_native_1setup
(JNIEnv *env, jclass clazz, jobject weak_this, jstring instance) {
ALOGD("=================== JNI call native_setup ========================");
std::shared_ptr<WifiStaServiceNativeListenerImpl> listener = std::make_shared<WifiStaServiceNativeListenerImpl>(env, clazz, weak_this);
ALOGD("=================== JNI call native_setup new WifiStaServiceNativeListenerImpl ok========================");
g_instance_name = std::string(env->GetStringUTFChars(instance, NULL));
WifiStaServiceNative::instantiate().registerListener(listener);
}
JNIEXPORT void JNICALL Java_com_yf_soa_wifistaservice_WifiStaServiceServiceStub_native_1finalize
(JNIEnv * env, jclass clazz) {
ALOGD("=================== JNI call native_finalize ========================");
}
JNIEXPORT void JNICALL Java_com_yf_soa_wifistaservice_WifiStaServiceServiceStub_native_1sendService
(JNIEnv *, jclass) {
ALOGD("=================== JNI call native_offerService ========================");
WifiStaServiceNative::instantiate().OfferService();
}
JNIEXPORT void JNICALL Java_com_yf_soa_wifistaservice_WifiStaServiceServiceStub_native_1stopSendService
(JNIEnv *, jclass) {
ALOGD("=================== JNI call native_stopOfferService ========================");
WifiStaServiceNative::instantiate().StopOfferService();
}
JNIEXPORT void JNICALL Java_com_yf_soa_wifistaservice_WifiStaServiceServiceStub_native_1notifyRssiChanged
(JNIEnv *env, jclass clazz, jbyteArray jrssichanged) {
ALOGD("=================== JNI call native_notifyRssiChanged ========================");
DataTypes::WifiAp arxml_rssiChanged;
DataTransfer::WifiAp transfer_rssichanged;
::com::yf::soa::wifistaservice::WifiAp proto_rssichanged;
if (jrssichanged) {
jbyte *data = env->GetByteArrayElements(jrssichanged, 0);
int data_len = env->GetArrayLength(jrssichanged);
proto_rssichanged.ParseFromArray(data, data_len);
env->ReleaseByteArrayElements(jrssichanged, data, 0);
transfer_rssichanged.fromProto(proto_rssichanged).toArxml(arxml_rssiChanged);
}
WifiStaServiceNative::instantiate().notifyRssiChanged(arxml_rssiChanged);
}
WifiStaServiceNativeListenerImpl::WifiStaServiceNativeListenerImpl(JNIEnv* env, jobject thiz, jobject weak_thiz) {
ALOGD("WifiStaServiceNativeListenerImpl::WifiStaServiceNativeListenerImpl");
jclass clazz = env->GetObjectClass(thiz);
if (clazz == NULL) {
return;
}
mClass = (jclass)g_WifiStaServiceServiceStubClass;
mObject = env->NewGlobalRef(weak_thiz);
}
WifiStaServiceNativeListenerImpl::~WifiStaServiceNativeListenerImpl() {
ALOGD("WifiStaServiceNativeListenerImpl::~WifiStaServiceNativeListenerImpl");
JNIEnv *env = getJNIEnv();
if (NULL == env) {
return;
}
env->DeleteGlobalRef(mObject);
env->DeleteGlobalRef(mClass);
syncDetachCurrentThread();
}
jbyteArray WifiStaServiceNativeListenerImpl::notify(JNIEnv* env, int msg, const jbyteArray obj) {
ALOGD("WifiStaServiceNativeListenerImpl::notify");
jbyteArray retobj = nullptr;
if (NULL == env) {
ALOGW("ERROR: JNIEnv is NULL LINE");
return retobj;
}
if (NULL == fields.post_event) {
ALOGW("notify fields.post_event is NULL");
return retobj;
}
ALOGW("notify msg %d", msg);
retobj = (jbyteArray)env->CallStaticObjectMethod(mClass, fields.post_event, mObject, msg, obj);
return retobj;
}
void WifiStaServiceNativeListenerImpl::syncDetachCurrentThread() {
}
WifiStaServiceNative::WifiStaServiceNative()
: yf::platform::WifiStaServiceSkeleton(ara::core::InstanceSpecifier(ara::core::StringView(g_instance_name.c_str(), g_instance_name.size())))
{
ALOGD("WifiStaServiceNative::WifiStaServiceNative");
}
WifiStaServiceNative::~WifiStaServiceNative() {
ALOGD("WifiStaServiceNative::~WifiStaServiceNative");
}
void WifiStaServiceNative::registerListener(const std::shared_ptr<WifiStaServiceNativeListener> listener) {
ALOGD("WifiStaServiceNative::registerListener");
m_listener = listener;
}
sovpap::core::Future<nm_wifistaservice::internal::methods::Activate::Output> WifiStaServiceNative::Activate() {
ara::core::Promise<nm_wifistaservice::internal::methods::Activate::Output> prom;
DataTransfer::ActivateOutput dataTransferOutput;
::com::yf::soa::wifistaservice::ActivateOutput protoOutput;
nm_wifistaservice::internal::methods::Activate::Output arxmlOutput;
JNIEnv *env = getJNIEnv();
jbyteArray jOutput = m_listener->notify(env, METHOD_ACTIVATE, nullptr);
if (jOutput) {
jbyte *data = env->GetByteArrayElements(jOutput, 0);
int data_len = env->GetArrayLength(jOutput);
protoOutput.ParseFromArray(data, data_len);
env->ReleaseByteArrayElements(jOutput, data, 0);
dataTransferOutput.fromProto(protoOutput).toArxml(arxmlOutput);
} else {
ALOGE("%s notify ret obj is null", __FUNCTION__);
}
m_listener->syncDetachCurrentThread();
prom.set_value(std::move(arxmlOutput));
return prom.get_future();
}
sovpap::core::Future<nm_wifistaservice::internal::methods::AddAp::Output> WifiStaServiceNative::AddAp(const DataTypes::WifiConfiguration& wifiConfiguration) {
ara::core::Promise<nm_wifistaservice::internal::methods::AddAp::Output> prom;
DataTransfer::AddApInput dataTransferInput;
DataTransfer::AddApOutput dataTransferOutput;
::com::yf::soa::wifistaservice::AddApInput protoInput;
::com::yf::soa::wifistaservice::AddApOutput protoOutput;
nm_wifistaservice::internal::methods::AddAp::Input arxmlInput;
nm_wifistaservice::internal::methods::AddAp::Output arxmlOutput;
JNIEnv *env = getJNIEnv();
arxmlInput.WifiConfiguration = wifiConfiguration;
dataTransferInput.fromArxml(arxmlInput).toProto(protoInput);
jbyteArray jInput = env->NewByteArray(protoInput.ByteSize());
jbyte *pInput = env->GetByteArrayElements(jInput, NULL);
protoInput.SerializeToArray(pInput, protoInput.ByteSize());
env->ReleaseByteArrayElements(jInput, pInput, 0);
jbyteArray jOutput = m_listener->notify(env, METHOD_ADDAP, jInput);
if (jOutput) {
jbyte *data = env->GetByteArrayElements(jOutput, 0);
int data_len = env->GetArrayLength(jOutput);
protoOutput.ParseFromArray(data, data_len);
env->ReleaseByteArrayElements(jOutput, data, 0);
dataTransferOutput.fromProto(protoOutput).toArxml(arxmlOutput);
} else {
ALOGE("%s notify ret obj is null", __FUNCTION__);
}
m_listener->syncDetachCurrentThread();
prom.set_value(std::move(arxmlOutput));
return prom.get_future();
}
void WifiStaServiceNative::notifyRssiChanged(const DataTypes::WifiAp& _rssiChanged) {
RssiChanged.Send(_rssiChanged);
}
void WifiStaServiceNative::notifyScanFinished(const DataTypes::WifiApList& _scanFinished) {
ScanFinished.Send(_scanFinished);
}
void WifiStaServiceNative::notifyStaConnChanged(const DataTypes::WifiAp& _staConnChanged) {
StaConnChanged.Send(_staConnChanged);
}
void WifiStaServiceNative::notifyStationChanged(const DataTypes::StationState_ref& _stationChanged) {
StationChanged.Send(_stationChanged);
}
}
}
#ifdef __cplusplus
}
#endif
总结一下
访问和修改实例变量操作步聚:
? 调用 GetObjectClass 函数获取实例对象的 Class 引用 ? 调用 GetFieldID 函数获取 Class 引用中某个实例变量的 ID ? 调用 GetXXXField 函数获取变量的值,需要传入实例变量所属对象和变量 ID ? 调用 SetXXXField 函数修改变量的值,需要传入实例变量所属对象、变量 ID 和变量的值
访问和修改静态变量操作步聚:
? 调用 FindClass 函数获取类的 Class 引用 ? 调用 GetStaticFieldID 函数获取 Class 引用中某个静态变量 ID ? 调用 GetStaticXXXField 函数获取静态变量的值,需要传入变量所属 Class 的引用和变量 ID ? 调用 SetStaticXXXField 函数设置静态变量的值,需要传入变量所属 Class 的引用、变量 ID和变量的 值
访问和修改实例变量操作步聚:
? 调用 GetObjectClass 函数获取实例对象的 Class 引用 ? 调用 GetFieldID 函数获取 Class 引用中某个实例变量的 ID ? 调用 GetXXXField 函数获取变量的值,需要传入实例变量所属对象和变量 ID ? 调用 SetXXXField 函数修改变量的值,需要传入实例变量所属对象、变量 ID 和变量的值
访问和修改静态变量操作步聚:
? 调用 FindClass 函数获取类的 Class 引用 ? 调用 GetStaticFieldID 函数获取 Class 引用中某个静态变量 ID ? 调用 GetStaticXXXField 函数获取静态变量的值,需要传入变量所属 Class 的引用和变量 ID ? 调用 SetStaticXXXField 函数设置静态变量的值,需要传入变量所属 Class 的引用、变量 ID和变量的 值
|