JNI серединавызов Java Ход метода :
① получать jclass тип переменной :
вызов jclass GetObjectClass(jobject obj) или jclass FindClass(const char* name) метод , получать jclass тип переменной ;
② проходитьотражениеполучатьметод :
вызов jmethodID GetMethodID(jclass clazz, const char* name, const char* sig) получать Java объектметод , вызов jmethodID GetStaticMethodID(jclass clazz, const char* name, const char* sig) получать Java класс изстатическийметод ;
③ вызовметод :
void CallVoidMethod(jobject obj, jmethodID methodID, …) вызов Java объектметод , void CallStaticVoidMethod(jclass clazz, jmethodID methodID, …) вызов Java изстатическийметод ;
CalXxxMethod метод , из которых Xxx да Java объектиз возвращаемое значение , невозвратный значениевызовдругойизметод ;
1 . прототип функции : Проходя внутрь Java объект ( jobject тип переменной ) , получать Java объект класса ( jclass тип переменной )
возвращаемое значение : возвращаться Java байт-код Class объект , переписываться C/C++ в jclass объект ; параметр : входящий Java объект ; ( Общий объект да состоит из JNI методвходящийиз )
struct _JNIEnv {
/* _JNIEnv Структура середина инкапсулирует JNINativeInterface указатель структуры */
const struct JNINativeInterface* functions;
...
// финальный вызовиз Ну давай же JNINativeInterface Инкапсуляция структуры середины GetObjectClassметод
jclass GetObjectClass(jobject obj)
{ return functions->GetObjectClass(this, obj); }
...
}
2. Пример кода:
extern "C"
JNIEXPORT void JNICALL
Java_kim_hsl_jni_MainActivity_jniObjectTest(JNIEnv *env, jobject instance, jobject student) {
//получать Java переписыватьсяиз Class объект
jclass student_class = env->GetObjectClass(student);
...
}
прототип функции : Проходя внутрьполный имя пакета.имя класса получать Java добрыйпереписыватьсяиз C/C++ среда jclass тип переменной ;
возвращаемое значение : возвращаться Java байт-код Class объект , переписываться C/C++ в jclass объект ; параметр : входящий полный Имя пакета/имя класса , Обратите внимание на использование “/” заменять “.” , нравиться “kim/hsl/jni/Teacher” ;
struct _JNIEnv {
/* _JNIEnv Структура середина инкапсулирует JNINativeInterface указатель структуры */
const struct JNINativeInterface* functions;
...
// финальный вызовиз Ну давай же JNINativeInterface Инкапсуляция структуры середины FindClass метод
jclass FindClass(const char* name)
{ return functions->FindClass(this, name); }
...
}
2. Пример кода: получать kim.hsl.jni.Teacher переписыватьсяиз jclass объект ;
extern "C"
JNIEXPORT void JNICALL
Java_kim_hsl_jni_MainActivity_jniObjectTest(JNIEnv *env, jobject instance, jobject student) {
...
// 5.2 получать Teacher добрый ( Переменную нужно освободить )
jclass class_teacher = env->FindClass("kim/hsl/jni/Teacher");
...
}
ссылка : JNI Правила подписи функций
При самостоятельном написании сигнатур функций легко допустить ошибки. , Все еще проблематично , рекомендоватьиспользовать javap инструмент ;
1 . байт-коддокумент : Сначала скомпилируйте Student из class байт-коддокумент , javap Заказ применяется непосредственно к файлу байт-кода. ;
2 . Android Studio середина Java После компиляции кода class расположение файла байт-кода : Различные версии из AS После компиляции положение избайт-кода меняется. , предположениесуществоватьсоответствующийиз Module Внизиз build Каталог середина для поиска файлов ,оказаться class байт-код Местосуществовать Оглавление ;
3 . яиз AS расположение каталога середина да : Y:\002_WorkSpace\001_AS\001_NDK_Hello\app\build\intermediates\javac\debug\compileDebugJavaWithJavac\classes , Выполнить в этом каталоге javap -s kim.hsl.jni.Student Заказ , Прямо сейчас Можетполучатьдобрыйв Подпись функции ;
4 . javap Формат заказа : javap -s весьимя пакета.имя класса ;
нравиться : хотетьполучать kim.hsl.jni.Student добрыйв Подпись функции , использовать javap -s kim.hsl.jni.Student Заказ ;
5 . выполнить заказ : существовать class Выполнить в каталоге javap -s kim.hsl.jni.Student Заказ ;
Y:\002_WorkSpace\001_AS\001_NDK_Hello\app\build\intermediates\javac\debug\compileDebugJavaWithJavac\classes>javap -s kim.hsl.jni.Student
Compiled from "Student.java"
public class kim.hsl.jni.Student {
public kim.hsl.jni.Student();
descriptor: ()V
public kim.hsl.jni.Student(int, java.lang.String);
descriptor: (ILjava/lang/String;)V
public int getAge();
descriptor: ()I
public void setAge(int);
descriptor: (I)V
public java.lang.String getName();
descriptor: ()Ljava/lang/String;
public void setName(java.lang.String);
descriptor: (Ljava/lang/String;)V
}
прототип функции : проходить jclass объект ,методимя,и методзнак, получать Java объект классапереписыватьсяизметод ID Прямо сейчас jmethodID тип переменной ;
возвращаемое значение : Java объект классапереписыватьсяизметод ID ( jmethodID тип переменной )
параметр :
struct _JNIEnv {
/* _JNIEnv Структура середина инкапсулирует JNINativeInterface указатель структуры */
const struct JNINativeInterface* functions;
...
// финальный вызовиз Ну давай же JNINativeInterface Инкапсуляция структуры середины GetMethodID метод
jmethodID GetMethodID(jclass clazz, const char* name, const char* sig)
{ return functions->GetMethodID(this, clazz, name, sig); }
...
}
2. Пример кода: получать Student добрыйиз getAge метод ;
student_class да Student добрыйпереписыватьсяиз C/C++ в jclass тип переменной ,Имя «getAge», “()I” подпись даметод , левая часть скобки дапараметр список тип подпись , кронштейн правый из I давозвращаемое значениетип int ;
extern "C"
JNIEXPORT void JNICALL
Java_kim_hsl_jni_MainActivity_jniObjectTest(JNIEnv *env, jobject instance, jobject student) {
...
//1 . получать Java переписыватьсяиз Class объект
jclass student_class = env->GetObjectClass(student);
//2 . получать Student из public int getAge() метод
jmethodID method_getAge = env->GetMethodID(student_class, "getAge" , "()I");
...
}
прототип функции : проходить jclass объект ,методимя,и методзнак, получать Java объект классапереписыватьсяизметод ID Прямо сейчас jmethodID тип переменной ;
возвращаемое значение : Java объект классапереписыватьсяизметод ID ( jmethodID тип переменной )
параметр :
struct _JNIEnv {
/* _JNIEnv Структура середина инкапсулирует JNINativeInterface указатель структуры */
const struct JNINativeInterface* functions;
...
// финальный вызовиз Ну давай же JNINativeInterface Инкапсуляция структуры середины GetStaticMethodID метод
jmethodID GetStaticMethodID(jclass clazz, const char* name, const char* sig)
{ return functions->GetStaticMethodID(this, clazz, name, sig); }
...
}
2. Пример кода: получать Student добрыйиз getAge метод ;
student_class да Student добрыйпереписыватьсяиз C/C++ в jclass тип переменной ,"logInfo" имя дамета, “(Ljava/lang/String;)V” подпись даметод , левая часть скобки дапараметр список тип подпись , кронштейн правый из V давозвращаемое значениетип void ;
extern "C"
JNIEXPORT void JNICALL
Java_kim_hsl_jni_MainActivity_jniObjectTest(JNIEnv *env, jobject instance, jobject student) {
...
//1 . получать Java переписыватьсяиз Class объект
jclass student_class = env->GetObjectClass(student);
//2 . получать Student из public static void logInfo(String info) метод
// Уведомлениездесьхотетьиспользовать GetStaticMethodID методотражение Долженстатическийметод jmethodID method_logInfo = env->GetStaticMethodID(student_class, "logInfo" , "(Ljava/lang/String;)V");
...
}
Уведомление : возвращаемое значениеипараметрдолжен Да Java тип ;
прототип функции : проходить Java объект , Java метод ID , и подписано в разделе «Функции в ближайшиеиз». параметрсписок ( переменный параметр ) ,отражениевызов Должен Java объектизметод ;
возвращаемое значение : Void , Уведомлениездесьизвозвращаемое значение Можеткда 8 добрый Основные данные , jboolean , jbyte , jshort ждатьтип , Вы также можете использовать да, чтобы указать тип jobject тип , только это 10 добрыйвозвращатьсятип , Нет другого ; ( Уведомление : возвращаемое значение Да Java тип )
параметр :
struct _JNIEnv {
/* _JNIEnv Структура середина инкапсулирует JNINativeInterface указатель структуры */
const struct JNINativeInterface* functions;
...
// финальный вызовиз Ну давай же JNINativeInterface Инкапсуляция структуры середины CallVoidMethod метод
void CallVoidMethod(jobject obj, jmethodID methodID, ...)
{
va_list args;
va_start(args, methodID);
functions->CallVoidMethodV(this, obj, methodID, args);
va_end(args);
}
...
}
2 . все Java методвызоввозвращаемое значениетип :
jobject (*CallObjectMethod)(JNIEnv*, jobject, jmethodID, ...);
jobject (*CallObjectMethodV)(JNIEnv*, jobject, jmethodID, va_list);
jobject (*CallObjectMethodA)(JNIEnv*, jobject, jmethodID, const jvalue*);
jboolean (*CallBooleanMethod)(JNIEnv*, jobject, jmethodID, ...);
jboolean (*CallBooleanMethodV)(JNIEnv*, jobject, jmethodID, va_list);
jboolean (*CallBooleanMethodA)(JNIEnv*, jobject, jmethodID, const jvalue*);
jbyte (*CallByteMethod)(JNIEnv*, jobject, jmethodID, ...);
jbyte (*CallByteMethodV)(JNIEnv*, jobject, jmethodID, va_list);
jbyte (*CallByteMethodA)(JNIEnv*, jobject, jmethodID, const jvalue*);
jchar (*CallCharMethod)(JNIEnv*, jobject, jmethodID, ...);
jchar (*CallCharMethodV)(JNIEnv*, jobject, jmethodID, va_list);
jchar (*CallCharMethodA)(JNIEnv*, jobject, jmethodID, const jvalue*);
jshort (*CallShortMethod)(JNIEnv*, jobject, jmethodID, ...);
jshort (*CallShortMethodV)(JNIEnv*, jobject, jmethodID, va_list);
jshort (*CallShortMethodA)(JNIEnv*, jobject, jmethodID, const jvalue*);
jint (*CallIntMethod)(JNIEnv*, jobject, jmethodID, ...);
jint (*CallIntMethodV)(JNIEnv*, jobject, jmethodID, va_list);
jint (*CallIntMethodA)(JNIEnv*, jobject, jmethodID, const jvalue*);
jlong (*CallLongMethod)(JNIEnv*, jobject, jmethodID, ...);
jlong (*CallLongMethodV)(JNIEnv*, jobject, jmethodID, va_list);
jlong (*CallLongMethodA)(JNIEnv*, jobject, jmethodID, const jvalue*);
jfloat (*CallFloatMethod)(JNIEnv*, jobject, jmethodID, ...);
jfloat (*CallFloatMethodV)(JNIEnv*, jobject, jmethodID, va_list);
jfloat (*CallFloatMethodA)(JNIEnv*, jobject, jmethodID, const jvalue*);
jdouble (*CallDoubleMethod)(JNIEnv*, jobject, jmethodID, ...);
jdouble (*CallDoubleMethodV)(JNIEnv*, jobject, jmethodID, va_list);
jdouble (*CallDoubleMethodA)(JNIEnv*, jobject, jmethodID, const jvalue*);
void (*CallVoidMethod)(JNIEnv*, jobject, jmethodID, ...);
void (*CallVoidMethodV)(JNIEnv*, jobject, jmethodID, va_list);
void (*CallVoidMethodA)(JNIEnv*, jobject, jmethodID, const jvalue*);
3 . пример кода : вызов Student добрыйиз getAge метод ;
student да Student объект класса , “method_getAge” даметод ID Поскольку нет параметра , Так что за изпеременный параметрсписокдлянулевой ;
extern "C"
JNIEXPORT void JNICALL
Java_kim_hsl_jni_MainActivity_jniObjectTest(JNIEnv *env, jobject instance, jobject student) {
...
//1 . получать Java переписыватьсяиз Class объект
jclass student_class = env->GetObjectClass(student);
//2 . получать Student из public static void logInfo(String info) метод
// Уведомлениездесьхотетьиспользовать GetStaticMethodID методотражение Долженстатическийметод jmethodID method_logInfo = env->GetStaticMethodID(student_class, "logInfo" , "(Ljava/lang/String;)V");
//3 . вызов Student из public int getAge() метод
jint age = env->CallIntMethod(student, method_getAge);
...
}
Уведомление : возвращаемое значениеипараметрдолжен Да Java тип ;
прототип функции : проходить Java объект класса ( Class объект переписываться C/C++ jclass типобъект ) , Java метод ID , и подписано в разделе «Функции в ближайшиеиз». параметрсписок ( переменный параметр ) ,отражениевызов Должен Java объектизметод ;
возвращаемое значение : Void , Уведомлениездесьизвозвращаемое значение Можеткда 8 добрый Основные данные , jboolean , jbyte , jshort ждатьтип , Вы также можете использовать да, чтобы указать тип jobject тип , только это 10 добрыйвозвращатьсятип , Нет другого ; ( Уведомление : возвращаемое значение Да Java тип )
параметр :
struct _JNIEnv {
/* _JNIEnv Структура середина инкапсулирует JNINativeInterface указатель структуры */
const struct JNINativeInterface* functions;
...
// финальный вызовиз Ну давай же JNINativeInterface Инкапсуляция структуры середины CallStaticVoidMethodV метод
void CallStaticVoidMethod(jclass clazz, jmethodID methodID, ...)
{
va_list args;
va_start(args, methodID);
functions->CallStaticVoidMethodV(this, clazz, methodID, args);
va_end(args);
}
...
}
2 . все Java методвызоввозвращаемое значениетип :
jobject (*CallStaticObjectMethod)(JNIEnv*, jclass, jmethodID, ...);
jobject (*CallStaticObjectMethodV)(JNIEnv*, jclass, jmethodID, va_list);
jobject (*CallStaticObjectMethodA)(JNIEnv*, jclass, jmethodID, const jvalue*);
jboolean (*CallStaticBooleanMethod)(JNIEnv*, jclass, jmethodID, ...);
jboolean (*CallStaticBooleanMethodV)(JNIEnv*, jclass, jmethodID,
va_list);
jboolean (*CallStaticBooleanMethodA)(JNIEnv*, jclass, jmethodID, const jvalue*);
jbyte (*CallStaticByteMethod)(JNIEnv*, jclass, jmethodID, ...);
jbyte (*CallStaticByteMethodV)(JNIEnv*, jclass, jmethodID, va_list);
jbyte (*CallStaticByteMethodA)(JNIEnv*, jclass, jmethodID, const jvalue*);
jchar (*CallStaticCharMethod)(JNIEnv*, jclass, jmethodID, ...);
jchar (*CallStaticCharMethodV)(JNIEnv*, jclass, jmethodID, va_list);
jchar (*CallStaticCharMethodA)(JNIEnv*, jclass, jmethodID, const jvalue*);
jshort (*CallStaticShortMethod)(JNIEnv*, jclass, jmethodID, ...);
jshort (*CallStaticShortMethodV)(JNIEnv*, jclass, jmethodID, va_list);
jshort (*CallStaticShortMethodA)(JNIEnv*, jclass, jmethodID, const jvalue*);
jint (*CallStaticIntMethod)(JNIEnv*, jclass, jmethodID, ...);
jint (*CallStaticIntMethodV)(JNIEnv*, jclass, jmethodID, va_list);
jint (*CallStaticIntMethodA)(JNIEnv*, jclass, jmethodID, const jvalue*);
jlong (*CallStaticLongMethod)(JNIEnv*, jclass, jmethodID, ...);
jlong (*CallStaticLongMethodV)(JNIEnv*, jclass, jmethodID, va_list);
jlong (*CallStaticLongMethodA)(JNIEnv*, jclass, jmethodID, const jvalue*);
jfloat (*CallStaticFloatMethod)(JNIEnv*, jclass, jmethodID, ...);
jfloat (*CallStaticFloatMethodV)(JNIEnv*, jclass, jmethodID, va_list);
jfloat (*CallStaticFloatMethodA)(JNIEnv*, jclass, jmethodID, const jvalue*);
jdouble (*CallStaticDoubleMethod)(JNIEnv*, jclass, jmethodID, ...);
jdouble (*CallStaticDoubleMethodV)(JNIEnv*, jclass, jmethodID, va_list);
jdouble (*CallStaticDoubleMethodA)(JNIEnv*, jclass, jmethodID, const jvalue*);
void (*CallStaticVoidMethod)(JNIEnv*, jclass, jmethodID, ...);
void (*CallStaticVoidMethodV)(JNIEnv*, jclass, jmethodID, va_list);
void (*CallStaticVoidMethodA)(JNIEnv*, jclass, jmethodID, const jvalue*);
3 . пример кода : вызов Student добрыйиз logInfo метод ;
student да Student объект класса , “method_logInfo” даметод ID info : jstring типпараметр , входящая строка в Java операция слоя ( Уведомление : параметр должен Да Java тип ) ;
extern "C"
JNIEXPORT void JNICALL
Java_kim_hsl_jni_MainActivity_jniObjectTest(JNIEnv *env, jobject instance, jobject student) {
...
//1 . получать Java переписыватьсяиз Class объект
jclass student_class = env->GetObjectClass(student);
//2 . получать Student из public static void logInfo(String info) метод
// Уведомлениездесьхотетьиспользовать GetStaticMethodID методотражение Долженстатическийметод jmethodID method_logInfo = env->GetStaticMethodID(student_class, "logInfo" , "(Ljava/lang/String;)V");
//3 . Подготовитьвходящийиз jstring параметр
jstring info = env->NewStringUTF("C/C++ Создать из Java Нить");
//4 . вызовстатическийметод : Уведомлениевходящийизпараметрдолжен Да Java типизпараметр
env->CallStaticVoidMethod(student_class, method_logInfo, info);
...
}
Полный пример кода :
extern "C"
JNIEXPORT void JNICALL
Java_kim_hsl_jni_MainActivity_jniObjectTest(JNIEnv *env, jobject instance, jobject student) {
/*
параметранализировать :
JNIEnv *env : JNI среда , указатель структуры , Структура середина инкапсулирует 209 индивидуальныйметод jobject instance : да MainActivity объект
jobject student : Java слой Создать из Student объект , входящий Native слой
*/
//существовать C/C++ серединавызов Student объектиз get метод
//1 . получать Java переписыватьсяиз Class объект
jclass student_class = env->GetObjectClass(student);
//2 . проходить Class изотражениеполучатьхотетьвызовизметод /*
прототип функции :
jmethodID GetMethodID(jclass clazz, const char* name, const char* sig)
{ return functions->GetMethodID(this, clazz, name, sig); }
параметриллюстрировать :
jclass clazz : использовать GetObjectClass методполучатьизвозвращаемое значение
const char* name : хотетьвызовизметодимя const char* sig : Подпись функции , См. форму подписи для конкретных правил подписи.
public int getAge() Подпись функции : ()I
левая сторона () : левая часть скобки дапараметр список тип подпись
Правая сторона I : кронштейн правый из I давозвращаемое значениетип int
public void setAge(int age) Подпись функции : (I)V
(I) выражатьлевая сторонапараметрсписок
Правая сторона V выражать其возвращаемое значениетипда void тип
Тип цитаты подпись : L + Полное имя + ;
javap инструмент :
Можеткиспользовать javap инструментполучатьметодзнак */
//получать Student из public int getAge() метод
jmethodID method_getAge = env->GetMethodID(student_class, "getAge" , "()I");
//получать Student из public void setAge(int age) метод
jmethodID method_setAge = env->GetMethodID(student_class, "setAge" , "(I)V");
//получать Student из public static void logInfo(String info) метод
// Уведомлениездесьхотетьиспользовать GetStaticMethodID методотражение Долженстатическийметод jmethodID method_logInfo = env->GetStaticMethodID(student_class, "logInfo" , "(Ljava/lang/String;)V");
//3 . вызов Java объектизметод
/*
вызов Java Цитироватьобъектизметод : быть основанным на возвращаемое значениетипдругой ,вызовдругойизметод нравитьсяфруктывозвращаемое значениеда int тип, Тогда вам нужен вызов CallIntMethod метод
нравитьсяфруктывозвращаемое значениеда void тип , Тогда вам нужен вызов CallVoidMethod метод
нравитьсяфруктывызовиздастатическийметод , Тогда вам нужен вызов
( Уведомление : вызовметодчасвходящийизпараметр Вседолженда C/C++ в Java типпараметр , нравиться jint , jstring ждать )
*/
//вызов Student объектиз public void setAge(int age) метод
env->CallVoidMethod(student, method_setAge, 18);
//вызов Student из public int getAge() метод
jint age = env->CallIntMethod(student, method_getAge);
/*
вызовстатическийметод :
1 . создавать Java нить
2 . вызовстатическийметод 3 . выпускать Java нить
*/
// создавать Java нить
jstring info = env->NewStringUTF("C/C++ Создать из Java Нить");
// вызовстатическийметод : Уведомлениевходящийизпараметр
env->CallStaticVoidMethod(student_class, method_logInfo, info);
// jstring info существоватьметодсерединасоздаватьновыйизнить , нуждатьсяхотетьсуществоватьметоддо концавыпускать Ссылкаобъект
env->DeleteLocalRef(info);
//4 . настраивать Student объект Атрибуты
/*
отражениеполучатьсвойство прототип функции :
jfieldID GetFieldID(jclass clazz, const char* name, const char* sig)
{ return functions->GetFieldID(this, clazz, name, sig); }
параметриллюстрировать :
jclass clazz : Java объект класса
const char* name : Имя свойства
const char* sig : Тип атрибута подпись
настраиватьотражениесвойствоценить :
прототип функции :
void SetIntField(jobject obj, jfieldID fieldID, jint value)
{ functions->SetIntField(this, obj, fieldID, value); }
параметриллюстрировать :
jobject obj : настраиватьобъект
jfieldID fieldID : проходить GetFieldID методполучатьизсвойство ID
jint value : хотетьнастраиватьизценить
Уведомление : настраиватьдругойтипизценить , вызовдругойизнастраиватьметод
*/
jfieldID age_field_id = env->GetFieldID(student_class, "age", "I");
env->SetIntField(student, age_field_id, 90);
// Проверка да Нет настройки прошла успешно
age = env->CallIntMethod(student, method_getAge);
//5 . существовать JNI серединасоздавать java объект , и настройки на другой объект
/*
получать Teacher добрый : проходитьвызов FindClass методполучать Teacher добрый
На данный момент известно два добрыхполучения jclass изметод
получать Teacher добрыйизструктураметод public Student(int age, String name)
структураметодизметодимя Да "<init>"
структураметодиз Подпись функциидля
Здесь есть что-то особенное: Уведомление : входящийприезжать Java методвпараметр , должен Да Java параметртип
нравиться jstring , jint , jintArray ждатьтип , не может быть C/C++ типвходящийпараметр
Особенно да char* нить , нуждатьсяхотетьиспользовать NewStringUTF Воля C/C++ нитьизменятьдля jstring типнить
создавать Teacher объект
Воля Teacher объектнастраивать Давать Student объект
*/
// 5.1 получать Student из public void setTeacher(Teacher teacher) метод
// Уведомление об этом Teacher изтип подписи да Lkim/hsl/jni/Teacher;
jmethodID method_setTeacher = env->GetMethodID(student_class, "setTeacher" , "(Lkim/hsl/jni/Teacher;)V");
LOGE("method_setTeacher");
// 5.2 получать Teacher добрый ( Переменную нужно освободить )
jclass class_teacher = env->FindClass("kim/hsl/jni/Teacher");
// 5.3 Найти метод структуры
jmethodID method_init = env->GetMethodID(class_teacher, "<init>", "(ILjava/lang/String;)V");
// 5.4 Подготовить Java типпараметр ( Переменную нужно освободить )
// Это место особенное : входящийприезжать Java методвпараметр Вседолженда Java параметр
jint teacher_age = 88;
jstring teacher_name = env->NewStringUTF("Tom Wang");
// 5.5 создавать Teacher объект ( Переменную нужно освободить )
jobject teacher = env->NewObject(class_teacher, method_init, teacher_age, teacher_name);
// 5.6 вызов Student объектиз setTeacher настраиватьметод
env->CallVoidMethod(student, method_setTeacher, teacher);
// 5.7 выпускатьвышепроходить FindClass NewStringUTF NewObject Создать из Цитироватьпеременная , Легко экономить память , также Можеткждатьприезжать конец области действия автоматическийвыпускать
// Использовать После завершения этих трех кавычек , больше никогдаиспользовать ; здесь特别предположение手动выпускать三индивидуальный Цитировать
// нравитьсяфрукты Не вручнуювыпускать , существовать Ссылка Объем После окончания , Он также будет автоматически удален
env->DeleteLocalRef(teacher_name);
env->DeleteLocalRef(teacher);
env->DeleteLocalRef(class_teacher);
}