JNI/NDK入门指南之C/C++通过JNI访问Java实例属性和类静态属性

  在前面的章节JNI/NDK入门指南之JNI访问数组中讲解了JNI对基本类型数组和各种引用类型数组的访问。今天我们继续向JNI的知识海洋进军讲解C/C++通过JNI访问Java实例属性和类静态属性的处理。本章内容有点多哦!



前言

通过前面的正佳我们知道了如何通过 JNI 函数来访问Native C/C++中的基本数据类型、字符串和数组这些数据类型。接下来我们接着学习C/C++本地代码如何通过JNI访问Java类中任意对象的属性交互。比如本地代码调用 Java 层某个对象的变量或者Java类的静态变量。静态变量也称为类变量(属性),在所有实例对象中共享同一份数据,可以直接通过【类名.变量名】来访问。实例变量也称为成员变量(属性),每个实例都拥有一份实例变量数据的拷贝,它们之间修改后的数据互不影响。下面让我们从JNI的访问对象操作函数开始,一步步带领读者攻破C/C++通过JNI访问Java实例变量和静态变量。好了,开车了。



一. 初探JNI访问Java实例属性处理函数

好了有了前面知识的铺垫,下面让我们来看看JNIEnv为我们提供了那些常见Java对象属性处理函数。

1.1 GetFieldID

函数原型: jfieldID GetFieldID (JNIEnv *env, jclass clazz, const char *name, const char *sig)
函数功能: 返回类的实例(非静态)域的属性 ID。该域由其名称及签名指定。访问属性系列函数Get<PrimitiveType>Field 及 Set<PrimitiveType>Field会使用。GetFieldID() 不能用于获取数组的长度域。应使用GetArrayLength()。
参数

  • env: JNIEnv接口指针
  • clazz: Java类对象,不是Java类的实例jobject。类对象,就是用来描述这种类,都有什么属性,什么方法的。所有的类,都存在一个类对象,这个类对象用于提供类本身的信息,比如有几种构造方法, 有多少属性,有哪些普通方法等等。
  • name: 该属性在类中的名称
  • sig:该属性的域签名,关于域签名可以参见章节JNI/NDK入门指南之JNI数据类型,描述符详解介绍

返回值:属性ID。如果操作失败,则返回NULL。
抛出:

  • NoSuchFieldError:如果找不到指定的域
  • ExceptionInInitializerError:如果由于异常而导致类初始化程序失败
  • OutOfMemoryError:如果系统内存不足

1.2 Get<PrimitiveType>Field 函数集

这里的PrimitiveType指代的是一系列的JNI数据类型,如果是引用类型的话PrimitiveType用Object替代。
函数原型: NativeType Get<PrimitiveType>Field (JNIEnv*env, jobject obj, jfieldID fieldID)
函数功能: 该函数集用于返回Java类的实例(非静态)域的值。要访问的域由通过调用GetFieldID() 而得到的域 ID 指定。
使用说明: 在下表中会将特定的基本类型数组构造函数及其返回值一一对应。在实际应用中把PrimitiveType替换为某个实际的基本类型数据类型,然后再将NativeType替换成对应的JNI Native Type即可。譬如我们以int型来说明,那么其对应的函数为:

jint GetIntField(JNIEnv * env, jobject obj, jfieldID fieldID);

参数:

  • env: JNIEnv接口指针
  • obj:Java类实例或者Java对象
  • fieldID:有效的域 ID

返回值:属性的内容。

函数集表格:

Get<PrimitiveType>函数名 NativeType JNI本地类型
GetObjectField() jobject
GetBooleanField() jboolean
GetByteField() jbyte
GetCharField() jchar
GetShortField() jshort
GetIntField() jint
GetLongField() jlong
GetFloatField() jfloat
GetDoubleField() jdouble

1.3 Set<PrimitiveType>Field 函数集

这里的PrimitiveType指代的是一系列的JNI数据类型,如果是引用类型的话PrimitiveType用Object替代。
函数原型: void Set<PrimitiveType>Field (JNIEnv *env, jobject obj, jfieldID fieldID, NativeType value)
函数功能: 该函数集用于设置对象的实例(非静态)属性的值。要访问的属性由通过调用GetFieldID() 而得到的属性 ID指定。
使用说明: 在下表中会将特定的基本类型数组构造函数及其返回值一一对应。在实际应用中把PrimitiveType替换为某个实际的基本类型数据类型,然后再将NativeType替换成对应的JNI Native Type即可。譬如我们以int型来说明,那么其对应的函数为:

void SetIntField(JNIEnv * env, jobject obj, jfieldID fieldID, jint value);

参数:

  • env: JNIEnv接口指针
  • obj: Java对象或者Java类实例(不能为NULL)
  • value: 传递给域的新值

函数集表格:

Set<PrimitiveType>函数名 NativeType JNI本地类型
SetObjectField() jobject
SetBooleanField() jboolean
SetByteField() jbyte
SetCharField() jchar
SetShortField() jshort
SetIntField() jint
SetLongField() jlong
SetFloatField() jfloat
SetDoubleField() jdouble


二. 初探JNI访问Java类对象属性处理函数

在前面的章节我们讲解了访问和修改Java对象属性的处理函数,下面让我们来看看JNIEnv为我们提供了那些常见Java类对象属性处理函数。

2.1 GetStaticFieldID

函数原型: jfieldID GetStaticFieldID (JNIEnv *env, jclass clazz, const char *name, const char *sig)
函数功能: 返回类对象(静态)域的属性 ID。该域由其名称及签名指定。访问属性系列函数GetStatic<PrimitiveType>Field 及 SetStatic<PrimitiveType>Field会使用。
参数

  • env: JNIEnv接口指针
  • clazz: Java类对象,不是Java类的实例jobject。类对象,就是用来描述这种类,都有什么属性,什么方法的。所有的类,都存在一个类对象,这个类对象用于提供类本身的信息,比如有几种构造方法, 有多少属性,有哪些普通方法等等。
  • name: 该属性在类中的名称
  • sig:该属性的域签名,关于域签名可以参见章节JNI/NDK入门指南之JNI数据类型,描述符详解介绍

返回值:属性ID。如果操作失败,则返回NULL。
抛出:

  • NoSuchFieldError:如果找不到指定的域
  • ExceptionInInitializerError:如果由于异常而导致类初始化程序失败
  • OutOfMemoryError:如果系统内存不足

2.2 GetStatic<PrimitiveType>Field 函数集

这里的PrimitiveType指代的是一系列的JNI数据类型,如果是引用类型的话PrimitiveType用Object替代。
函数原型: NativeType GetStatic<PrimitiveType>Field (JNIEnv*env, jclass clazz, jfieldID fieldID)
函数功能: 该函数集用于返回Java类对象(静态)域的值。要访问的域由通过调用GetStaticFieldID() 而得到的域 ID 指定。
使用说明: 在下表中会将特定的基本类型数组构造函数及其返回值一一对应。在实际应用中把PrimitiveType替换为某个实际的基本类型数据类型,然后再将NativeType替换成对应的JNI Native Type即可。譬如我们以int型来说明,那么其对应的函数为:

jint GetStaticIntField(JNIEnv * env, jclass clazz, jfieldID fieldID);

参数:

  • env: JNIEnv接口指针
  • clazz:Java类对象
  • fieldID:有效的域 ID

返回值:静态属性的内容。

函数集表格:

GetStatic<PrimitiveType>函数名 NativeType JNI本地类型
GetStaticObjectField() jobject
GetStaticBooleanField() jboolean
GetStaticByteField() jbyte
GetStaticCharField() jchar
GetStaticShortField() jshort
GetStaticIntField() jint
GetStaticLongField() jlong
GetStaticFloatField() jfloat
GetStaticDoubleField() jdouble

2.3 SetStatic<PrimitiveType>Field 函数集

这里的PrimitiveType指代的是一系列的JNI数据类型,如果是引用类型的话PrimitiveType用Object替代。
函数原型: void SetStatic<PrimitiveType>Field (JNIEnv *env, jclass clazz, jfieldID fieldID, NativeType value)
函数功能: 该函数集用于设置Java类对象(静态)属性的值。要访问的属性由通过调用GetStaticFieldID() 而得到的属性 ID指定。
使用说明: 在下表中会将特定的基本类型数组构造函数及其返回值一一对应。在实际应用中把PrimitiveType替换为某个实际的基本类型数据类型,然后再将NativeType替换成对应的JNI Native Type即可。譬如我们以int型来说明,那么其对应的函数为:

void SetStaticIntField(JNIEnv * env, jobject obj, jfieldID fieldID, jint value);

参数:

  • env: JNIEnv接口指针
  • clazz: Java类对象(不能为NULL)
  • value: 传递给域的新值

函数集表格:

SetStatic<PrimitiveType>函数名 NativeType JNI本地类型
SetStaticObjectField() jobject
SetStaticBooleanField() jboolean
SetStaticByteField() jbyte
SetStaticCharField() jchar
SetStaticShortField() jshort
SetStaticIntField() jint
SetStaticLongField() jlong
SetStaticFloatField() jfloat
SetStaticDoubleField() jdouble

可以看出它们与实例属性的唯一区别在于第二个参数jclass classzz代表的是类引用,而不是类实例。



三. JNI访问Java实例属性和类静态属性实战分析

前面的章节,我们将JNI访问Java实例属性和类静态属性中有关访问函数集,一网打净了(当然是夸张说法了)。说得再多不练,都是纸上谈兵,下面我们来实战一把,跟紧我要开战了,可别走丢了。

3.1 JNI访问和修改Java实例属性

好了前面的理论知识我们已经OK了,那么接下来都懂的必须来点实战的东西,不能光说不练。让我带领读者来看看怎么通过JNI访问和修改Java实例属性。
Java端代码:
Java实例所属类JNIFieldClass.java代码:

package com.xxx.jni.field;public class JNIFieldClass {private String mString = "Hello JNI, this is normal string !";private int mInt = 1;@Overridepublic String toString() {return "JNIFieldClass [mString=" + mString + ", mInt=" + mInt + "]";}
}

Java端Native方法定义JNIAccessFieldManager.java代码:

package com.xxx.jni.field;/**** * C/C++访问Java类的实例变量和静态变量* */
public class JNIAccessFieldManager {public native void accessInstanceFiled(JNIFieldClass mJniFieldClass);static {System.loadLibrary("accesfield");// 加载so库}
}

Java端测试代码:

    private void operateInstanceFiled(){JNIFieldClass mJniFieldClass = new JNIFieldClass();Log.e("ACCESS_FIELD","operateInstanceFiled before : " + mJniFieldClass.toString());JNIAccessFieldManager mAccessFieldManager = new JNIAccessFieldManager();mAccessFieldManager.accessInstanceFiled(mJniFieldClass);Log.e("ACCESS_FIELD","operateInstanceFiled after : " + mJniFieldClass.toString());}

JNI端代码:
Java中Native方法对应com_xxx_jni_field_JNIAccessFieldManager.h代码如下:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_xxx_jni_field_JNIAccessFieldManager */#ifndef _Included_com_xxx_jni_field_JNIAccessFieldManager
#define _Included_com_xxx_jni_field_JNIAccessFieldManager
#ifdef __cplusplus
extern "C" {
#endif/** Class:     com_xxx_jni_field_JNIAccessFieldManager* Method:    accessInstanceFiled* Signature: (Lcom/xxx/jni/field/JNIFieldClass;)V*/
JNIEXPORT void JNICALL Java_com_xxx_jni_field_JNIAccessFieldManager_accessInstanceFiled(JNIEnv *, jobject, jobject);#ifdef __cplusplus
}
#endif
#endif

对应的com_xxx_jni_field_JNIAccessFieldManager.cpp代码如下:

#include "com_xxx_jni_field_JNIAccessFieldManager.h"
#include <stdio.h>
#include <android/log.h>
#include <jni.h>
#include <stdlib.h>
#include <errno.h>#define TAG "ACCESS_FIELD"
#define LOGE(TAG,...) __android_log_print(ANDROID_LOG_INFO,TAG,__VA_ARGS__)//将jstring转换成char *
char* jstringToNative(JNIEnv *env, jstring jstr)
{if ((env)->ExceptionCheck() == JNI_TRUE || jstr == NULL){(env)->ExceptionDescribe();(env)->ExceptionClear();//printf("jstringToNative函数转换时,传入的参数str为空");return NULL;} jbyteArray bytes = 0; jthrowable exc; char *result = 0; if ((env)->EnsureLocalCapacity(2) < 0) { return 0; /* out of memory error */ } jclass jcls_str = (env)->FindClass("java/lang/String"); jmethodID MID_String_getBytes = (env)->GetMethodID(jcls_str, "getBytes", "()[B"); bytes = (jbyteArray)(env)->CallObjectMethod(jstr, MID_String_getBytes); exc = (env)->ExceptionOccurred(); if (!exc) { jint len = (env)->GetArrayLength( bytes); result = (char *)malloc(len + 1); if (result == 0) { //JNU_ThrowByName( "java/lang/OutOfMemoryError", 	0); (env)->DeleteLocalRef(bytes); return 0; } (env)->GetByteArrayRegion(bytes, 0, len, (jbyte *)result); result[len] = 0; /* NULL-terminate */ } else { (env)->DeleteLocalRef( exc); } (env)->DeleteLocalRef( bytes); return (char*)result; } //将char *  转换成 jstring
jstring nativeTojstring( JNIEnv* env,const char* str )
{	//定义java String类 strClassjclass strClass = (env)->FindClass("java/lang/String");//获取java String类方法String(byte[],String)的构造器,用于将本地byte[]数组转换为一个新StringjmethodID ctorID = (env)->GetMethodID( strClass, "<init>", "([BLjava/lang/String;)V");//建立byte数组jbyteArray bytes = (env)->NewByteArray( (jsize)strlen(str));//将char* 转换为byte数组(env)->SetByteArrayRegion( bytes, 0, (jsize)strlen(str), (jbyte*)str);//设置String, 保存语言类型,用于byte数组转换至String时的参数jstring encoding = (env)->NewStringUTF( "utf-8"); //将byte数组转换为java String,并输出return (jstring)(env)->NewObject( strClass, ctorID, bytes, encoding); 
}/** Class:     com_xxx_jni_field_JNIAccessFieldManager* Method:    accessInstanceFiled* Signature: (Lcom/xxx/jni/field/JNIFieldClass;)V*/
JNIEXPORT void JNICALL Java_com_xxx_jni_field_JNIAccessFieldManager_accessInstanceFiled(JNIEnv * env, jobject object, jobject object_in)
{jclass clazz;//JNIFieldClass类引用jfieldID mString_fieldID;//JNIFieldClass类对象变量mString属性IDjfieldID mInt_fieldID;//JNIFieldClass类对象变量mInt属性ID/******获取JNIFieldClass类实例变量mString的值并修改********///1.通过JNIFieldClass类实例object_in获取Class的引用clazz = env->GetObjectClass(object_in);if(clazz == NULL){LOGE(TAG,"GetObjectClass failed\n");return;}//2.获取JNIFieldClass类的实例变量mString的属性ID//其中第二参数是变量的名称,第三个参数是变量类型的描述符mString_fieldID = env->GetFieldID(clazz, "mString",  "Ljava/lang/String;");if(mString_fieldID == NULL){LOGE(TAG,"GetFieldID  mString failed\n");return;		}//3.获取JNIFieldClass类实例变量mString的值,并打印出来jstring j_string = (jstring)env->GetObjectField(object_in, mString_fieldID);char * buf = jstringToNative(env, j_string);LOGE(TAG,"object_in.mString : %s\n", buf);free(buf);//4.修改类实例变量mStriing的值char * buf_out = "Hello Java, I am JNI!";env->SetObjectField(object_in, mString_fieldID, nativeTojstring(env, buf_out));//5.释放局部引用env->DeleteLocalRef(j_string);/******获取JNIFieldClass类实例int型变量mInt的值并修改********///6.获取JNIFieldClass类实例int型变量mString的属性IDmInt_fieldID = env->GetFieldID(clazz, "mInt", "I");if(mInt_fieldID == NULL){LOGE(TAG,"GetFieldID  mInt failed\n");return;			}//7.获取JNIFieldClass实例变量mInt的值jint mInt = env->GetIntField(object_in, mInt_fieldID);LOGE(TAG,"object_in.mInt : %d\n", mInt);//8.修改JNIFieldClass实例变量mInt的值env->SetIntField(object_in, mInt_fieldID, 100);//9.删除局部引用,即对JNIFieldClass的类引用env->DeleteLocalRef(clazz);	
}

运行演示:

λ adb logcat  -s  ACCESS_FIELD
--------- beginning of main
--------- beginning of system
12-26 08:22:33.111  8575  8575 E ACCESS_FIELD: operateInstanceFiled before : JNIFieldClass [mString=Hello JNI, this is normal string !, mInt=1]
12-26 08:22:33.116  8575  8575 I ACCESS_FIELD: object_in.mString : Hello JNI, this is normal string !
12-26 08:22:33.117  8575  8575 I ACCESS_FIELD: object_in.mInt : 1
12-26 08:22:33.117  8575  8575 E ACCESS_FIELD: operateInstanceFiled after : JNIFieldClass [mString=Hello Java, I am JNI!, mInt=100]

案例分析:
在本例中,Java类JNIAccessFieldManager中定义了一个accessInstanceFiled的Native方法,参数类型是JNIFieldClass的实例,在其本地方法中我们会通过该实例进行对Java实例属性的访问和修改一系列操作。下面让我们对本地代码以一一分析。
获取JNIFieldClass类实例变量mString的值并修改:
在该部分代码中我们会通过JNI系列函数获取Java类实例属性的值并修改,然后将修改前后的值打印出来。
(1) 通过JNIFieldClass类对象object_in获取Class的引用,可能获取到的为NULL,必须加上异常判断。
(2) 调用函数GetFieldID获取JNIFieldClass类的实例变量mString的属性ID,其中第二参数是变量的名称,第三个参数是变量类型的描述符。
(3) 调用GetObjectField获取JNIFieldClass类实例变量mString的值,并打印出来。
(4) 调用SetObjectField修改类实例变量mStriing的值。
(5) 调用DeleteLocalRef释放局部引用。

获取JNIFieldClass类实例int型变量mInt的值并修改:
(1) 调用GetFieldID获取JNIFieldClass类实例int型变量mString的属性ID。
(2) 调用GetIntField获取JNIFieldClass实例变量mInt的值。
(3) 调用SetIntField修改JNIFieldClass实例变量mInt的值。
(4) 最后调用DeleteLocalRef删除局部引用,即对JNIFieldClass的类引用


3.2 JNI访问和修改Java类对象静态属性

在前面的章节带领读者见证了JNI访问和修改Java实例属性,那么接下来让我带领读者来看看怎么通过JNI访问和修改Java类对象静态属性。
Java端代码:
Java实例所属类JNIFieldClass.java代码:

package com.xxx.jni.field;public class JNIFieldClass {private static String mStaticString = "Hello JNI, this is static string !";private static int mStaticInt = 0;public static String toStaticString() {return "JNIFieldClass [mStaticString=" + mStaticString + ", mStaticInt=" + mStaticInt + "]";}
}

Java端Native方法定义JNIAccessFieldManager.java代码:

package com.xxx.jni.field;/**** * C/C++访问Java类的实例变量和静态变量* */
public class JNIAccessFieldManager {public native void accessStaticField();static {System.loadLibrary("accesfield");// 加载so库}
}

Java端测试代码:

    private void operateStaticFiled(){Log.e("ACCESS_FIELD","operateStaticFiled before : " + JNIFieldClass.toStaticString());JNIAccessFieldManager mAccessFieldManager = new JNIAccessFieldManager();mAccessFieldManager.accessStaticField();Log.e("ACCESS_FIELD","operateStaticFiled after : " + JNIFieldClass.toStaticString());}

JNI端代码:
Java中Native方法对应com_xxx_jni_field_JNIAccessFieldManager.h代码如下:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_xxx_jni_field_JNIAccessFieldManager */#ifndef _Included_com_xxx_jni_field_JNIAccessFieldManager
#define _Included_com_xxx_jni_field_JNIAccessFieldManager
#ifdef __cplusplus
extern "C" {
#endif/** Class:     com_xxx_jni_field_JNIAccessFieldManager* Method:    accessStaticField* Signature: ()V*/
JNIEXPORT void JNICALL Java_com_xxx_jni_field_JNIAccessFieldManager_accessStaticField(JNIEnv *, jobject);#ifdef __cplusplus
}
#endif
#endif

对应的com_xxx_jni_field_JNIAccessFieldManager.cpp代码如下:

#include "com_xxx_jni_field_JNIAccessFieldManager.h"
#include <stdio.h>
#include <android/log.h>
#include <jni.h>
#include <stdlib.h>
#include <errno.h>#define TAG "ACCESS_FIELD"
#define LOGE(TAG,...) __android_log_print(ANDROID_LOG_INFO,TAG,__VA_ARGS__)//将jstring转换成char *
char* jstringToNative(JNIEnv *env, jstring jstr)
{if ((env)->ExceptionCheck() == JNI_TRUE || jstr == NULL){(env)->ExceptionDescribe();(env)->ExceptionClear();//printf("jstringToNative函数转换时,传入的参数str为空");return NULL;} jbyteArray bytes = 0; jthrowable exc; char *result = 0; if ((env)->EnsureLocalCapacity(2) < 0) { return 0; /* out of memory error */ } jclass jcls_str = (env)->FindClass("java/lang/String"); jmethodID MID_String_getBytes = (env)->GetMethodID(jcls_str, "getBytes", "()[B"); bytes = (jbyteArray)(env)->CallObjectMethod(jstr, MID_String_getBytes); exc = (env)->ExceptionOccurred(); if (!exc) { jint len = (env)->GetArrayLength( bytes); result = (char *)malloc(len + 1); if (result == 0) { //JNU_ThrowByName( "java/lang/OutOfMemoryError", 	0); (env)->DeleteLocalRef(bytes); return 0; } (env)->GetByteArrayRegion(bytes, 0, len, (jbyte *)result); result[len] = 0; /* NULL-terminate */ } else { (env)->DeleteLocalRef( exc); } (env)->DeleteLocalRef( bytes); return (char*)result; } //将char *  转换成 jstring
jstring nativeTojstring( JNIEnv* env,const char* str )
{	//定义java String类 strClassjclass strClass = (env)->FindClass("java/lang/String");//获取java String类方法String(byte[],String)的构造器,用于将本地byte[]数组转换为一个新StringjmethodID ctorID = (env)->GetMethodID( strClass, "<init>", "([BLjava/lang/String;)V");//建立byte数组jbyteArray bytes = (env)->NewByteArray( (jsize)strlen(str));//将char* 转换为byte数组(env)->SetByteArrayRegion( bytes, 0, (jsize)strlen(str), (jbyte*)str);//设置String, 保存语言类型,用于byte数组转换至String时的参数jstring encoding = (env)->NewStringUTF( "utf-8"); //将byte数组转换为java String,并输出return (jstring)(env)->NewObject( strClass, ctorID, bytes, encoding); 
}/** Class:     com_xxx_jni_field_JNIAccessFieldManager* Method:    accessStaticField* Signature: ()V*/
JNIEXPORT void JNICALL Java_com_xxx_jni_field_JNIAccessFieldManager_accessStaticField(JNIEnv * env, jobject object)
{jclass clazz;//JNIFieldClass类引用jfieldID mStaticString_fieldID;//JNIFieldClass类静态变量mStaticString属性IDjfieldID mStaticInt_filedID;//JNIFieldClass类静态变量StaticInt属性ID/******获取JNIFieldClass类静态变量mStaticString的值并修改********///1.通过FindClass获取JNIFieldClass的类引用clazz = env->FindClass("com/xxx/jni/field/JNIFieldClass");if(clazz == NULL){LOGE(TAG,"FindClass failed\n");return;}//2.获取JNIFieldClass类静态变量mStaticString的属性IDmStaticString_fieldID = env->GetStaticFieldID(clazz, "mStaticString", "Ljava/lang/String;");	if(mStaticString_fieldID == NULL){LOGE(TAG,"mStaticString_fieldID  mStaticString failed\n");return;		}//3.获取JNIFieldClass类静态变量mStaticString的值并打印jstring j_string = (jstring)env->GetStaticObjectField(clazz, mStaticString_fieldID);char * buf = jstringToNative(env, j_string);LOGE(TAG,"JNIFieldClass.mString : %s\n", buf);free(buf);//4.修改JNIFieldClass类静态变量mStaticString的值char * buf_out = "Hello Java, I am JNI!";env->SetStaticObjectField(clazz, mStaticString_fieldID, nativeTojstring(env, buf_out));//5.释放局部引用env->DeleteLocalRef(j_string);/******获取JNIFieldClass类静态变量mStaticInt的值并修改********///6.获取JNIFieldClass类静态变量mStaticInt的属性IDmStaticInt_filedID = env->GetStaticFieldID(clazz, "mStaticInt", "I");if(mStaticInt_filedID == NULL){LOGE(TAG,"GetStaticFieldID  mStaticInt failed\n");return;		}//7.获取JNIFieldClass类静态变量mStaticInt的值并打印jint mInt = env->GetStaticIntField(clazz, mStaticInt_filedID);LOGE(TAG,"JNIFieldClass.mInt : %d\n", mInt);//8.修改JNIFieldClass类静态变量mStaticInt的值env->SetStaticIntField(clazz, mStaticInt_filedID, 1000);//9.删除局部引用,即对JNIFieldClass的类引用env->DeleteLocalRef(clazz);	}

运行演示:

λ aadb logcat  -s  ACCESS_FIELD
--------- beginning of main
--------- beginning of system
12-26 09:27:58.422  8733  8733 E ACCESS_FIELD: operateStaticFiled before : JNIFieldClass [mStaticString=Hello JNI, this is static string !, mStaticInt=0]
12-26 09:27:58.426  8733  8733 I ACCESS_FIELD: JNIFieldClass.mString : Hello JNI, this is static string !
12-26 09:27:58.426  8733  8733 I ACCESS_FIELD: JNIFieldClass.mInt : 0
12-26 09:27:58.426  8733  8733 E ACCESS_FIELD: operateStaticFiled after : JNIFieldClass [mStaticString=Hello Java, I am JNI!, mStaticInt=1000]

案例分析:
在本例中,Java类JNIAccessFieldManager中定义了一个accessStaticField的Native方法,可以看到我们这里是没有传入任何参数的,因为我们是对类对象做访问不需要它的实例。下面让我们对本地代码以一一分析。
获取JNIFieldClass类静态变量mStaticString的值并修改:
在该部分代码中我们会通过JNI系列函数获取Java类对象静态属性的值并修改,然后将修改前后的值打印出来。
(1) 通过FindClass获取JNIFieldClass的类引用,可能获取到的为NULL,必须加上异常判断。
(2) 调用函数GetStaticFieldID获取JNIFieldClass类静态变量mStaticString的属性ID。
(3) 调用GetStaticObjectField获取JNIFieldClass类静态变量mStaticString的值并打印。
(4) 调用SetStaticObjectField修改JNIFieldClass类静态变量mStaticString的值。
(5) 调用DeleteLocalRef释放局部引用。

获取JNIFieldClass类静态变量mStaticInt的值并修改:
(1) 调用GetStaticFieldID获取JNIFieldClass类静态变量mStaticInt的属性ID。
(2) 调用GetStaticIntField获取JNIFieldClass类静态变量mStaticInt的值并打印。
(3) 调用SetStaticIntField修改JNIFieldClass类静态变量mStaticInt的值。
(4) 最后调用DeleteLocalRef删除局部引用,即对JNIFieldClass的类引用
好了到这里就解析完成了。



四. 总结思考

大家对前面的实例有没有一个疑问呢,为啥我们通过JNI能访问Java类实例私有属性和Java类对象私有静态属性呢。这是为什么呢?

public class JNIFieldClass {private static String mStaticString = "Hello JNI, this is static string !";//私有private String mString = "Hello JNI, this is normal string !";//私有private static int mStaticInt = 0;//私有private int mInt = 1;//私有
}

由于 JNI 函数是直接操作虚拟机中的数据结构,不受 Java 访问修饰符的限制。即,在本地代码中可以调用JNI 函数可以访问 Java 对象中的非 public 属性和方法。这也为操作Java对象中private的属性或者方法的一种思路。

前面的知识讲解都是为了引出最后的结论,下面让我们小结一把:
JNI访问和修改Java实例属性操作步聚:

  • 调用 GetObjectClass 函数获取实例对象的 Class 引用
  • 调用 GetFieldID 函数获取 Class 引用中某个实例变量的 ID
  • 调用 GetXXXField 函数获取变量的值,需要传入实例变量所属对象和变量 ID
  • 调用 SetXXXField 函数修改变量的值,需要传入实例变量所属对象、变量 ID 和变量的值
    JNI访问和修改Java类对象静态属性操作步聚:
  • 调用 FindClass 函数获取类的 Class 引用
  • 调用 GetStaticFieldID 函数获取 Class 引用中某个静态变量 ID
  • 调用 GetStaticXXXField 函数获取静态变量的值,需要传入变量所属 Class 的引用和变量 ID
  • 调用 SetStaticXXXField 函数设置静态变量的值,需要传入变量所属 Class 的引用、变量 ID和变量的


写在最后

  各位读者看官朋友们,关于C/C++通过JNI访问Java实例属性和类静态属性就告一段落了。本篇几乎将JNI中访问Java实例属性和类静态属性各种情况都讲到了,只要仔细阅读本章,应该以后没有访问Java实例属性和类静态属性问题能难住各位了。在最后麻烦读者朋友们如果本篇对你有帮助,关注和点赞一下,当然如果有错误和不足的地方也可以拍砖。

查看全文
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

相关文章

  1. 架构导论

    架构导论 01 | 架构设计的特性 1、架构设计的思维和程序设计的思维差异很大1)架构设计的关键思维是判断和取舍,程序设计的关键思维是逻辑和实现。 2)用写代码的思维去思考架构,会导致很多困惑。2、架构设计没有体系化的培训和训练机制1)架构设计一般只能自己慢慢摸索,效率…...

    2024/4/18 11:23:14
  2. 事件处理

    @click;触发事件,调用方法事件修饰符;.stop.prevent.capture.self.once.passive<!-- 阻止单击事件继续传播 --> <a v-on:click.stop="doThis"></a><!-- 提交事件不再重载页面 --> <form v-on:submit.prevent="onSubmit">&…...

    2024/4/22 22:21:39
  3. android (四)手势

    事件 和 手势 事件处理 :物理事件处理 触摸屏事件处理 手势物理事件处理:基于监听事件处理 基于回调事件处理基于回调的时间处理: 重写Activity 回调方法 OnTouchEvent + OnKeyDown + OnKeyUp 基于回调处理事件,采用通用性事件 比如在物理按键 1.物理事件 提供三个事件 : …...

    2024/4/28 16:09:46
  4. Http and Https

    HTTP缓存http缓存都是从第二次请求开始的。第一次请求资源时,服务器返回资源,并在respone header头中回传资源的缓存参数;第二次请求时,浏览器判断这些请求参数,命中强缓存就直接200,否则就把请求参数加到request header头中传给服务器,看是否命中协商缓存,命中则返回3…...

    2024/4/28 21:24:57
  5. iOS 内购详解-代码篇

    内购项目-代码篇一、分步骤说明1、获取商品列表2、苹果服务器返回的可购买商品3、下单购买商品4、购买队列状态变化,判断购买状态是否成功5、交易验证6、拿到的收据信息是,此App所有购买的记录7、恢复商品二、详细代码三、内购项目-App Store Connect 详解篇祝您好运~ 一、分…...

    2024/4/29 0:58:34
  6. 【计算理论与算法分析设计】 2. 输水管道问题

    输水管道问题 问题描述 某公司计划建造一条由东向西的主输水管道。该管道要穿过一个有n口水井的区域。从每口水井都要有一条输水管道沿最短路经(或南或北)与主管道相连。如果给定n口水井的位置,即它们的x坐标(东西向)和y坐标(南北向),应如何确定主管道的最优位置,即使各…...

    2024/4/28 14:58:47
  7. 一个空格引发的血案

    报错信息为找不到name属性,实际上是由于在65行的"${listCertMemberid } "中右大括号后多加了一个空格。。。。。才导致数据读不出。 org.apache.catalina.core.StandardWrapperValve invoke 严重: Servlet.service() for servlet [dispatcherServlet] in context wi…...

    2024/4/28 11:05:38
  8. 使用 Java 调用阿里云短信服务

    使用 Java 调用阿里云短信服务使用 Java 调用阿里云短信服务登录阿里云申请短信服务申请签名和模板申请AccessKey获得阿里云账户的操控权限测试短信发送使用Java调用阿里云短信服务验证码随机生成测试Main方法 使用 Java 调用阿里云短信服务 短信验证码想必大家都不陌生,在很多…...

    2024/4/28 21:49:26
  9. 一篇文章了解网络相关知识——网络基础知识汇总

    什么是链接? 链接是指两个设备之间的连接。它包括用于一个设备能够与另一个设备通信的电缆类型和协议。 OSI参考类型的层次是什么? OSI7层:应用层、表示层、会话层、传输层、网络层、数据链路层、物理层。 什么是骨干网? 骨干网络是集中的基础设施,旨在将不同的路由和数据…...

    2024/4/28 4:36:11
  10. JNI/NDK入门指南之Eclipse集成NDK开发环境并使用

    JNI/NDK入门指南之Eclipse集成NDK开发环境并使用在前面的章节里面,我们已经了解了JNI开发所需要掌握的相关基本知识。那么在本篇文章里面将要介绍Eclipse集成NDK开发环境。配置使用步骤这里我会以一个简单的Android中使用JNI开发的列子来说明,怎么在Eclipse中集成NDK开发环境…...

    2024/4/27 21:22:18
  11. vue打包时 babel报错:Cannot read property ‘bindings‘ of null

    原因应该是我所用babel版本和webpack4.0不兼容 所以我升级了babel: npm install -D babel-loader @babel/core @babel/preset-env 然后再更改.babelrc的配置: { “presets”: [ “@babel/preset-env” ] }...

    2024/4/28 12:13:58
  12. 分享2个PPT动画,很有意思!

    Hello,大家好,我是利兄~最近很多朋友让我聊聊PPT动画,正好最近逛国外的网站,发现了几个动画案例,给大家拆解一下。在拆解的过程中,自己也有非常大的收获。先看案例第一个案例。我们先找好图片,做一张类似的,像下图这样,是不是还不错。很多人看到这个动画,第一个想到的…...

    2024/5/1 13:45:56
  13. 洛谷P1255 数楼梯

    题目描述 楼梯有N阶,上楼可以一步上一阶,也可以一步上二阶。 编一个程序,计算共有多少种不同的走法。 输入格式 一个数字,楼梯数。 输出格式 走的方式几种。 输入输出样例 输入 #1复制 4输出 #1复制 5说明/提示 60% N<=50 100% N<=5000) 题解 这道题一眼就可以看出,是…...

    2024/4/28 22:22:23
  14. 计算机网络基础(五)---分层体系(结构)的优点

    计算机网络分层体系(结构)的好处:(1)各层之间是独立的。基层并不需要知道它的下层是如何实现的。 而仅仅需要知道该层通过层间的接口即界面)所提供的服务。由于每层只实现种相对独立的功能,因而可将一个难以处理的复杂问题分解为若干个较容易处理的更小一些的问题。 这样,…...

    2024/4/27 22:25:37
  15. 给定一个数组,输出数组元素中的最大值(小练习)

    public class TestCompare {public static void main(String[] args) {int[] nums = {1,2,3,4,9}; int max = 0;for(int i = 0;i < nums.length;i++) {if(nums[i] > max) {max = nums[i];}}System.out.println(max);} }...

    2024/4/29 0:10:30
  16. win10扬声器没有声音但出入耳机有声音

    问题描述 win10系统自带扬声器没有声音,但是插入耳机有声音正常 解决方法 打开“控制面板”,然后按照下图进行操作:...

    2024/4/28 8:59:19
  17. Spring boot+Shiro+MyBatis-Plus搭建企业级快速开发平台源码分享

    一个 Java EE 企业级快速开发平台,基于经典技术组合(Spring Boot、Spring MVC、Apache Shiro、MyBatis-Plus、Freemarker、Bootstrap、AdminLTE)采用经典开发模式,让初学者能够更快的入门并投入到团队开发中去。 在线代码生成功能,包括核心模块如:组织机构、角色用户、菜…...

    2024/4/28 20:17:11
  18. nowcoder14694 栗酱的数列

    链接 点击跳转 题解 把原来的式子移项,就得到a1−a2=b2−b1a_1-a_2=b_2-b1a1​−a2​=b2​−b1这样的式子,那么(−a1)−(−a2)=b1−b2(-a_1)-(-a_2) = b_1-b_2(−a1​)−(−a2​)=b1​−b2​ 所以先把第一个序列取相反数,然后直接转换成差分序列的子串匹配问题 kmpkmpkmp即可…...

    2024/4/28 3:12:00
  19. 2 运行流程

    ...

    2024/4/29 1:58:48
  20. 重学ES系列之拓展运算符

    <!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>扩展运算符</title> </head> <…...

    2024/4/28 4:50:38

最新文章

  1. FP16、BF16、INT8、INT4精度模型加载所需显存以及硬件适配的分析

    大家好,我是herosunly。985院校硕士毕业,现担任算法研究员一职,热衷于机器学习算法研究与应用。曾获得阿里云天池比赛第一名,CCF比赛第二名,科大讯飞比赛第三名。拥有多项发明专利。对机器学习和深度学习拥有自己独到的见解。曾经辅导过若干个非计算机专业的学生进入到算法…...

    2024/5/3 21:32:37
  2. 梯度消失和梯度爆炸的一些处理方法

    在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言&#xff0c;在此感激不尽。 权重和梯度的更新公式如下&#xff1a; w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...

    2024/3/20 10:50:27
  3. ChatGPT 初学者指南

    原文&#xff1a;ChatGPT for Beginners 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 介绍 如果您一直关注新闻和趋势&#xff0c;您可能已经在某个地方读到或听到过&#xff0c;Sam Altman 的生成式人工智能平台 ChatGPT 已经将人工智能推向了一个新的高度 - 许多…...

    2024/5/3 2:27:51
  4. 论文阅读AI工具链

    文献检索 可以利用智谱清言来生成合适的文献检索式&#xff0c;并根据需要不断调整。 谷歌学术 在Google Scholar中进行检索时&#xff0c;您可以使用类似的逻辑来构建您的搜索式&#xff0c;但是语法会有所不同。Google Scholar的搜索框接受普通的文本搜索&#xff0c;但是…...

    2024/5/3 14:44:57
  5. 【外汇早评】美通胀数据走低,美元调整

    原标题:【外汇早评】美通胀数据走低,美元调整昨日美国方面公布了新一期的核心PCE物价指数数据,同比增长1.6%,低于前值和预期值的1.7%,距离美联储的通胀目标2%继续走低,通胀压力较低,且此前美国一季度GDP初值中的消费部分下滑明显,因此市场对美联储后续更可能降息的政策…...

    2024/5/1 17:30:59
  6. 【原油贵金属周评】原油多头拥挤,价格调整

    原标题:【原油贵金属周评】原油多头拥挤,价格调整本周国际劳动节,我们喜迎四天假期,但是整个金融市场确实流动性充沛,大事频发,各个商品波动剧烈。美国方面,在本周四凌晨公布5月份的利率决议和新闻发布会,维持联邦基金利率在2.25%-2.50%不变,符合市场预期。同时美联储…...

    2024/5/2 16:16:39
  7. 【外汇周评】靓丽非农不及疲软通胀影响

    原标题:【外汇周评】靓丽非农不及疲软通胀影响在刚结束的周五,美国方面公布了新一期的非农就业数据,大幅好于前值和预期,新增就业重新回到20万以上。具体数据: 美国4月非农就业人口变动 26.3万人,预期 19万人,前值 19.6万人。 美国4月失业率 3.6%,预期 3.8%,前值 3…...

    2024/4/29 2:29:43
  8. 【原油贵金属早评】库存继续增加,油价收跌

    原标题:【原油贵金属早评】库存继续增加,油价收跌周三清晨公布美国当周API原油库存数据,上周原油库存增加281万桶至4.692亿桶,增幅超过预期的74.4万桶。且有消息人士称,沙特阿美据悉将于6月向亚洲炼油厂额外出售更多原油,印度炼油商预计将每日获得至多20万桶的额外原油供…...

    2024/5/2 9:28:15
  9. 【外汇早评】日本央行会议纪要不改日元强势

    原标题:【外汇早评】日本央行会议纪要不改日元强势近两日日元大幅走强与近期市场风险情绪上升,避险资金回流日元有关,也与前一段时间的美日贸易谈判给日本缓冲期,日本方面对汇率问题也避免继续贬值有关。虽然今日早间日本央行公布的利率会议纪要仍然是支持宽松政策,但这符…...

    2024/4/27 17:58:04
  10. 【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响

    原标题:【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响近日伊朗局势升温,导致市场担忧影响原油供给,油价试图反弹。此时OPEC表态稳定市场。据消息人士透露,沙特6月石油出口料将低于700万桶/日,沙特已经收到石油消费国提出的6月份扩大出口的“适度要求”,沙特将满…...

    2024/4/27 14:22:49
  11. 【外汇早评】美欲与伊朗重谈协议

    原标题:【外汇早评】美欲与伊朗重谈协议美国对伊朗的制裁遭到伊朗的抗议,昨日伊朗方面提出将部分退出伊核协议。而此行为又遭到欧洲方面对伊朗的谴责和警告,伊朗外长昨日回应称,欧洲国家履行它们的义务,伊核协议就能保证存续。据传闻伊朗的导弹已经对准了以色列和美国的航…...

    2024/4/28 1:28:33
  12. 【原油贵金属早评】波动率飙升,市场情绪动荡

    原标题:【原油贵金属早评】波动率飙升,市场情绪动荡因中美贸易谈判不安情绪影响,金融市场各资产品种出现明显的波动。随着美国与中方开启第十一轮谈判之际,美国按照既定计划向中国2000亿商品征收25%的关税,市场情绪有所平复,已经开始接受这一事实。虽然波动率-恐慌指数VI…...

    2024/4/30 9:43:09
  13. 【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试

    原标题:【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试美国和伊朗的局势继续升温,市场风险情绪上升,避险黄金有向上突破阻力的迹象。原油方面稍显平稳,近期美国和OPEC加大供给及市场需求回落的影响,伊朗局势并未推升油价走强。近期中美贸易谈判摩擦再度升级,美国对中…...

    2024/4/27 17:59:30
  14. 【原油贵金属早评】市场情绪继续恶化,黄金上破

    原标题:【原油贵金属早评】市场情绪继续恶化,黄金上破周初中国针对于美国加征关税的进行的反制措施引发市场情绪的大幅波动,人民币汇率出现大幅的贬值动能,金融市场受到非常明显的冲击。尤其是波动率起来之后,对于股市的表现尤其不安。隔夜美国股市出现明显的下行走势,这…...

    2024/5/2 15:04:34
  15. 【外汇早评】美伊僵持,风险情绪继续升温

    原标题:【外汇早评】美伊僵持,风险情绪继续升温昨日沙特两艘油轮再次发生爆炸事件,导致波斯湾局势进一步恶化,市场担忧美伊可能会出现摩擦生火,避险品种获得支撑,黄金和日元大幅走强。美指受中美贸易问题影响而在低位震荡。继5月12日,四艘商船在阿联酋领海附近的阿曼湾、…...

    2024/4/28 1:34:08
  16. 【原油贵金属早评】贸易冲突导致需求低迷,油价弱势

    原标题:【原油贵金属早评】贸易冲突导致需求低迷,油价弱势近日虽然伊朗局势升温,中东地区几起油船被袭击事件影响,但油价并未走高,而是出于调整结构中。由于市场预期局势失控的可能性较低,而中美贸易问题导致的全球经济衰退风险更大,需求会持续低迷,因此油价调整压力较…...

    2024/4/26 19:03:37
  17. 氧生福地 玩美北湖(上)——为时光守候两千年

    原标题:氧生福地 玩美北湖(上)——为时光守候两千年一次说走就走的旅行,只有一张高铁票的距离~ 所以,湖南郴州,我来了~ 从广州南站出发,一个半小时就到达郴州西站了。在动车上,同时改票的南风兄和我居然被分到了一个车厢,所以一路非常愉快地聊了过来。 挺好,最起…...

    2024/4/29 20:46:55
  18. 氧生福地 玩美北湖(中)——永春梯田里的美与鲜

    原标题:氧生福地 玩美北湖(中)——永春梯田里的美与鲜一觉醒来,因为大家太爱“美”照,在柳毅山庄去寻找龙女而错过了早餐时间。近十点,向导坏坏还是带着饥肠辘辘的我们去吃郴州最富有盛名的“鱼头粉”。说这是“十二分推荐”,到郴州必吃的美食之一。 哇塞!那个味美香甜…...

    2024/4/30 22:21:04
  19. 氧生福地 玩美北湖(下)——奔跑吧骚年!

    原标题:氧生福地 玩美北湖(下)——奔跑吧骚年!让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 啊……啊……啊 两…...

    2024/5/1 4:32:01
  20. 扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!

    原标题:扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!扒开伪装医用面膜,翻六倍价格宰客!当行业里的某一品项火爆了,就会有很多商家蹭热度,装逼忽悠,最近火爆朋友圈的医用面膜,被沾上了污点,到底怎么回事呢? “比普通面膜安全、效果好!痘痘、痘印、敏感肌都能用…...

    2024/4/27 23:24:42
  21. 「发现」铁皮石斛仙草之神奇功效用于医用面膜

    原标题:「发现」铁皮石斛仙草之神奇功效用于医用面膜丽彦妆铁皮石斛医用面膜|石斛多糖无菌修护补水贴19大优势: 1、铁皮石斛:自唐宋以来,一直被列为皇室贡品,铁皮石斛生于海拔1600米的悬崖峭壁之上,繁殖力差,产量极低,所以古代仅供皇室、贵族享用 2、铁皮石斛自古民间…...

    2024/4/28 5:48:52
  22. 丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者

    原标题:丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者【公司简介】 广州华彬企业隶属香港华彬集团有限公司,专注美业21年,其旗下品牌: 「圣茵美」私密荷尔蒙抗衰,产后修复 「圣仪轩」私密荷尔蒙抗衰,产后修复 「花茵莳」私密荷尔蒙抗衰,产后修复 「丽彦妆」专注医学护…...

    2024/4/30 9:42:22
  23. 广州械字号面膜生产厂家OEM/ODM4项须知!

    原标题:广州械字号面膜生产厂家OEM/ODM4项须知!广州械字号面膜生产厂家OEM/ODM流程及注意事项解读: 械字号医用面膜,其实在我国并没有严格的定义,通常我们说的医美面膜指的应该是一种「医用敷料」,也就是说,医用面膜其实算作「医疗器械」的一种,又称「医用冷敷贴」。 …...

    2024/5/2 9:07:46
  24. 械字号医用眼膜缓解用眼过度到底有无作用?

    原标题:械字号医用眼膜缓解用眼过度到底有无作用?医用眼膜/械字号眼膜/医用冷敷眼贴 凝胶层为亲水高分子材料,含70%以上的水分。体表皮肤温度传导到本产品的凝胶层,热量被凝胶内水分子吸收,通过水分的蒸发带走大量的热量,可迅速地降低体表皮肤局部温度,减轻局部皮肤的灼…...

    2024/4/30 9:42:49
  25. 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...

    解析如下&#xff1a;1、长按电脑电源键直至关机&#xff0c;然后再按一次电源健重启电脑&#xff0c;按F8健进入安全模式2、安全模式下进入Windows系统桌面后&#xff0c;按住“winR”打开运行窗口&#xff0c;输入“services.msc”打开服务设置3、在服务界面&#xff0c;选中…...

    2022/11/19 21:17:18
  26. 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。

    %读入6幅图像&#xff08;每一幅图像的大小是564*564&#xff09; f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...

    2022/11/19 21:17:16
  27. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...

    win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面&#xff0c;在等待界面中我们需要等待操作结束才能关机&#xff0c;虽然这比较麻烦&#xff0c;但是对系统进行配置和升级…...

    2022/11/19 21:17:15
  28. 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...

    有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows&#xff0c;请勿关闭计算机”的提示&#xff0c;要过很久才能进入系统&#xff0c;有的用户甚至几个小时也无法进入&#xff0c;下面就教大家这个问题的解决方法。第一种方法&#xff1a;我们首先在左下角的“开始…...

    2022/11/19 21:17:14
  29. win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...

    置信有很多用户都跟小编一样遇到过这样的问题&#xff0c;电脑时发现开机屏幕显现“正在配置Windows Update&#xff0c;请勿关机”(如下图所示)&#xff0c;而且还需求等大约5分钟才干进入系统。这是怎样回事呢&#xff1f;一切都是正常操作的&#xff0c;为什么开时机呈现“正…...

    2022/11/19 21:17:13
  30. 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...

    Win7系统开机启动时总是出现“配置Windows请勿关机”的提示&#xff0c;没过几秒后电脑自动重启&#xff0c;每次开机都这样无法进入系统&#xff0c;此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一&#xff1a;开机按下F8&#xff0c;在出现的Windows高级启动选…...

    2022/11/19 21:17:12
  31. 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...

    有不少windows10系统用户反映说碰到这样一个情况&#xff0c;就是电脑提示正在准备windows请勿关闭计算机&#xff0c;碰到这样的问题该怎么解决呢&#xff0c;现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法&#xff1a;1、2、依次…...

    2022/11/19 21:17:11
  32. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...

    今天和大家分享一下win7系统重装了Win7旗舰版系统后&#xff0c;每次关机的时候桌面上都会显示一个“配置Windows Update的界面&#xff0c;提示请勿关闭计算机”&#xff0c;每次停留好几分钟才能正常关机&#xff0c;导致什么情况引起的呢&#xff1f;出现配置Windows Update…...

    2022/11/19 21:17:10
  33. 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...

    只能是等着&#xff0c;别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚&#xff0c;只能是考虑备份数据后重装系统了。解决来方案一&#xff1a;管理员运行cmd&#xff1a;net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...

    2022/11/19 21:17:09
  34. 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?

    原标题&#xff1a;电脑提示“配置Windows Update请勿关闭计算机”怎么办&#xff1f;win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢&#xff1f;一般的方…...

    2022/11/19 21:17:08
  35. 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...

    关机提示 windows7 正在配置windows 请勿关闭计算机 &#xff0c;然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;关机提示 windows7 正在配…...

    2022/11/19 21:17:05
  36. 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...

    钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...

    2022/11/19 21:17:05
  37. 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...

    前几天班里有位学生电脑(windows 7系统)出问题了&#xff0c;具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面&#xff0c;长时间没反应&#xff0c;无法进入系统。这个问题原来帮其他同学也解决过&#xff0c;网上搜了不少资料&#x…...

    2022/11/19 21:17:04
  38. 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...

    本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法&#xff0c;并在最后教给你1种保护系统安全的好方法&#xff0c;一起来看看&#xff01;电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中&#xff0c;添加了1个新功能在“磁…...

    2022/11/19 21:17:03
  39. 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...

    许多用户在长期不使用电脑的时候&#xff0c;开启电脑发现电脑显示&#xff1a;配置windows更新失败&#xff0c;正在还原更改&#xff0c;请勿关闭计算机。。.这要怎么办呢&#xff1f;下面小编就带着大家一起看看吧&#xff01;如果能够正常进入系统&#xff0c;建议您暂时移…...

    2022/11/19 21:17:02
  40. 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...

    配置windows update失败 还原更改 请勿关闭计算机&#xff0c;电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;配置windows update失败 还原更改 请勿关闭计算机&#x…...

    2022/11/19 21:17:01
  41. 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...

    不知道大家有没有遇到过这样的一个问题&#xff0c;就是我们的win7系统在关机的时候&#xff0c;总是喜欢显示“准备配置windows&#xff0c;请勿关机”这样的一个页面&#xff0c;没有什么大碍&#xff0c;但是如果一直等着的话就要两个小时甚至更久都关不了机&#xff0c;非常…...

    2022/11/19 21:17:00
  42. 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...

    当电脑出现正在准备配置windows请勿关闭计算机时&#xff0c;一般是您正对windows进行升级&#xff0c;但是这个要是长时间没有反应&#xff0c;我们不能再傻等下去了。可能是电脑出了别的问题了&#xff0c;来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...

    2022/11/19 21:16:59
  43. 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...

    我们使用电脑的过程中有时会遇到这种情况&#xff0c;当我们打开电脑之后&#xff0c;发现一直停留在一个界面&#xff1a;“配置Windows Update失败&#xff0c;还原更改请勿关闭计算机”&#xff0c;等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢&#xff0…...

    2022/11/19 21:16:58
  44. 如何在iPhone上关闭“请勿打扰”

    Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...

    2022/11/19 21:16:57