Parcourir la source

# feat:JNI中三种引用类型的使用
## 局部引用
- 获取局部引用在JVM中使用
- 验证局部引用是会被GC
##全局引用
- 获取全局引用在JVM中使用
- 验证全局引用不会被GC
## 弱全局引用
- 获取弱全局引用在JVM中使用
- 验证弱全局引用会被GC

yang yi il y a 2 semaines
Parent
commit
8f5ba9d102

+ 27 - 0
c/reference/JNI_globalReference.c

@@ -0,0 +1,27 @@
+#include "space_anyi_jni_reference_GlobalReferenceTest.h"
+JNIEXPORT jlong JNICALL Java_space_anyi_jni_reference_GlobalReferenceTest_getPersonHandler(JNIEnv *env, jobject this){
+    //1.获取对应的jclass
+    jclass class_Person = (*env)->FindClass(env, "Lspace/anyi/jni/reference/Person;");
+    //2.获取对应的构造方法
+    jmethodID constructor = (*env)->GetMethodID(env, class_Person, "<init>", "(Ljava/lang/String;I)V");
+    //3.创建对象
+    jstring name = (*env)->NewStringUTF(env, "杨逸");
+    jobject person = (*env)->NewObject(env, class_Person, constructor,name,18);
+    //4.获取全局引用
+    jobject globalReference = (*env)->NewGlobalRef(env, person);
+    //5.转换为句柄,使用intptr_t类型作为中间类型,避免精度丢失
+    jlong handler = (jlong)(intptr_t)globalReference;
+    return handler;
+}
+
+JNIEXPORT jobject JNICALL Java_space_anyi_jni_reference_GlobalReferenceTest_getPerson(JNIEnv *env, jobject this, jlong handler){
+    //1.通过句柄获取全局引用,使用intptr_t类型作为中间类型
+    jobject person = (jobject)(intptr_t)handler;
+    //2.返回对象
+    return person;
+}
+
+JNIEXPORT void JNICALL Java_space_anyi_jni_reference_GlobalReferenceTest_freePerson(JNIEnv *env, jobject this, jlong handler){
+    //1.通过句柄释放全局引用的内存
+    (*env)->DeleteGlobalRef(env, (jobject)(intptr_t)handler);
+}

+ 11 - 0
c/reference/JNI_localReference.c

@@ -0,0 +1,11 @@
+#include "space_anyi_jni_reference_LocalReferenceTest.h"
+JNIEXPORT jobject JNICALL Java_space_anyi_jni_reference_LocalReferenceTest_getPerson(JNIEnv *env, jobject this){
+    //1.获取对应的jclass
+    jclass class_Person = (*env)->FindClass(env, "Lspace/anyi/jni/reference/Person;");
+    //2.获取对应的构造方法
+    jmethodID constructor = (*env)->GetMethodID(env, class_Person, "<init>", "(Ljava/lang/String;I)V");
+    //3.创建对象
+    jstring name = (*env)->NewStringUTF(env, "杨逸");
+    jobject person = (*env)->NewObject(env, class_Person, constructor,name,18);
+    return person;
+}

+ 28 - 0
c/reference/JNI_weakGlobalReference.c

@@ -0,0 +1,28 @@
+#include "space_anyi_jni_reference_WeakGlobalReferenceTest.h"
+JNIEXPORT jlong JNICALL Java_space_anyi_jni_reference_WeakGlobalReferenceTest_getPersonHandler(JNIEnv *env, jobject this){
+        //1.获取对应的jclass
+        jclass class_Person = (*env)->FindClass(env, "Lspace/anyi/jni/reference/Person;");
+        //2.获取对应的构造方法
+        jmethodID constructor = (*env)->GetMethodID(env, class_Person, "<init>", "(Ljava/lang/String;I)V");
+        //3.创建对象
+        jstring name = (*env)->NewStringUTF(env, "杨逸-弱引用");
+        jobject person = (*env)->NewObject(env, class_Person, constructor,name,18);
+        //4.获取全局弱引用
+        jobject weakGlobalReference = (*env)->NewWeakGlobalRef(env, person);
+        //5.转换为句柄,使用intptr_t类型作为中间类型,避免精度丢失
+        jlong handler = (jlong)(intptr_t)weakGlobalReference;
+        return handler;
+}
+
+JNIEXPORT jobject JNICALL Java_space_anyi_jni_reference_WeakGlobalReferenceTest_getPerson(JNIEnv *env, jobject this, jlong handler){
+    //1.通过句柄获取全局弱引用,使用intptr_t类型作为中间类型
+    jobject person = (jobject)(intptr_t)handler;
+    return person;
+}
+
+JNIEXPORT void JNICALL Java_space_anyi_jni_reference_WeakGlobalReferenceTest_freePerson(JNIEnv *env, jobject this, jlong handler){
+    //1.通过句柄获取全局弱引用,使用intptr_t类型作为中间类型
+    jobject weakGlobalReference = (jobject)(intptr_t)handler;
+    //2.释放全局弱引用
+    (*env)->DeleteWeakGlobalRef(env, weakGlobalReference);
+}

+ 37 - 0
c/reference/space_anyi_jni_reference_GlobalReferenceTest.h

@@ -0,0 +1,37 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class space_anyi_jni_reference_GlobalReferenceTest */
+
+#ifndef _Included_space_anyi_jni_reference_GlobalReferenceTest
+#define _Included_space_anyi_jni_reference_GlobalReferenceTest
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class:     space_anyi_jni_reference_GlobalReferenceTest
+ * Method:    getPersonHandler
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_space_anyi_jni_reference_GlobalReferenceTest_getPersonHandler
+  (JNIEnv *, jobject);
+
+/*
+ * Class:     space_anyi_jni_reference_GlobalReferenceTest
+ * Method:    getPerson
+ * Signature: (J)Lspace/anyi/jni/reference/Person;
+ */
+JNIEXPORT jobject JNICALL Java_space_anyi_jni_reference_GlobalReferenceTest_getPerson
+  (JNIEnv *, jobject, jlong);
+
+/*
+ * Class:     space_anyi_jni_reference_GlobalReferenceTest
+ * Method:    freePerson
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_space_anyi_jni_reference_GlobalReferenceTest_freePerson
+  (JNIEnv *, jobject, jlong);
+
+#ifdef __cplusplus
+}
+#endif
+#endif

+ 21 - 0
c/reference/space_anyi_jni_reference_LocalReferenceTest.h

@@ -0,0 +1,21 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class space_anyi_jni_reference_LocalReferenceTest */
+
+#ifndef _Included_space_anyi_jni_reference_LocalReferenceTest
+#define _Included_space_anyi_jni_reference_LocalReferenceTest
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class:     space_anyi_jni_reference_LocalReferenceTest
+ * Method:    getPerson
+ * Signature: ()Lspace/anyi/jni/reference/Person;
+ */
+JNIEXPORT jobject JNICALL Java_space_anyi_jni_reference_LocalReferenceTest_getPerson
+  (JNIEnv *, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif

+ 37 - 0
c/reference/space_anyi_jni_reference_WeakGlobalReferenceTest.h

@@ -0,0 +1,37 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class space_anyi_jni_reference_WeakGlobalReferenceTest */
+
+#ifndef _Included_space_anyi_jni_reference_WeakGlobalReferenceTest
+#define _Included_space_anyi_jni_reference_WeakGlobalReferenceTest
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class:     space_anyi_jni_reference_WeakGlobalReferenceTest
+ * Method:    getPersonHandler
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_space_anyi_jni_reference_WeakGlobalReferenceTest_getPersonHandler
+  (JNIEnv *, jobject);
+
+/*
+ * Class:     space_anyi_jni_reference_WeakGlobalReferenceTest
+ * Method:    getPerson
+ * Signature: (J)Lspace/anyi/jni/reference/Person;
+ */
+JNIEXPORT jobject JNICALL Java_space_anyi_jni_reference_WeakGlobalReferenceTest_getPerson
+  (JNIEnv *, jobject, jlong);
+
+/*
+ * Class:     space_anyi_jni_reference_WeakGlobalReferenceTest
+ * Method:    freePerson
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_space_anyi_jni_reference_WeakGlobalReferenceTest_freePerson
+  (JNIEnv *, jobject, jlong);
+
+#ifdef __cplusplus
+}
+#endif
+#endif

+ 235 - 0
src/main/java/space/anyi/jni/reference/Main.java

@@ -0,0 +1,235 @@
+package space.anyi.jni.reference;
+
+import java.util.Objects;
+
+/**
+ * @ProjectName: JNI_learn
+ * @FileName: Main
+ * @Author: 杨逸
+ * @Data:2026/3/4 21:25
+ * @Description:
+ */
+public class Main {
+    static {
+        System.load("E:\\tmp\\JNI_learn\\c\\reference\\JNI_globalReference.dll");
+        System.load("E:\\tmp\\JNI_learn\\c\\reference\\JNI_weakGlobalReference.dll");
+        System.load("E:\\tmp\\JNI_learn\\c\\reference\\JNI_localReference.dll");
+    }
+    public static void main(String[] args) {
+        //GlobalReferenceTest.test();
+        //WeakGlobalReferenceTest.testJVMGC();
+        LocalReferenceTest.test();
+    }
+}
+class LocalReferenceTest{
+    static LocalReferenceTest localReferenceTest = new LocalReferenceTest();
+
+    /**
+     * 测试在JVM中使用JNI创建的对象局部引用
+     * @description:
+     * @author: 杨逸
+     * @data:2026/03/05 21:06:10
+     * @since 1.0.0
+     */
+    static void test(){
+        Person person = localReferenceTest.getPerson();
+        System.gc();
+        try {
+            Thread.sleep(1000*5);
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+        }
+        System.out.println(Objects.isNull(person));
+        System.out.println("person = " + person);
+    }
+    static void testJVMGC(){
+        while (true){
+            localReferenceTest.getPerson();
+        }
+    }
+
+    /**
+     * 在JNI中创建一个局部引用,并返回对象
+     * @return {@code Person }
+     * @description:
+     * @author: 杨逸
+     * @data:2026/03/05 22:35:30
+     * @since 1.0.0
+     */
+    native Person getPerson();
+}
+class GlobalReferenceTest{
+    static GlobalReferenceTest globalReferenceTest = new GlobalReferenceTest();
+
+    /**
+     * 测试在JVM中使用JNI创建的对象全局引用
+     * @description:
+     * @author: 杨逸
+     * @data:2026/03/05 21:06:10
+     * @since 1.0.0
+     */
+    static void test(){
+        //获取全局引用的句柄
+        long personHandler = globalReferenceTest.getPersonHandler();
+
+        //根据句柄获取全局引用对象
+        Person person = globalReferenceTest.getPerson(personHandler);
+        System.out.println("person.getName() = " + person.getName());
+        System.out.println("person.getAge() = " + person.getAge());
+        System.out.println(person);
+        //释放全局引用
+        globalReferenceTest.freePerson(personHandler);
+    }
+
+    /**
+     * 测试JNI创建的对象全局引用是否会被JVM垃圾回收
+     * @description:
+     * @author: 杨逸
+     * @data:2026/03/05 21:06:34
+     * @since 1.0.0
+     */
+    static void testJVMGC(){
+        //获取全局引用的句柄
+        long personHandler = globalReferenceTest.getPersonHandler();
+        //根据句柄获取全局引用对象
+        Person person = globalReferenceTest.getPerson(personHandler);
+        System.gc();
+        try {
+            Thread.sleep(1000*5);
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+        }
+        while (true){
+            globalReferenceTest.getPersonHandler();
+        }
+    }
+    /**
+     * 在JNI中创建一个全局引用,并返回句柄
+     * @return long 全局引用的句柄
+     * @description:
+     * @author: 杨逸
+     * @data:2026/03/04 21:29:12
+     * @since 1.0.0
+     */
+    native long getPersonHandler();
+
+    /**
+     * 根据句柄获取全局引用对象
+     * @param handler 句柄
+     * @return {@code Person } 全局引用对象
+     * @description:
+     * @author: 杨逸
+     * @data:2026/03/04 21:30:09
+     * @since 1.0.0
+     */
+    native Person getPerson(long handler);
+
+    /**
+     * 释放JNI创建的全局引用
+     * @param handler 句柄
+     * @description:
+     * @author: 杨逸
+     * @data:2026/03/04 21:30:38
+     * @since 1.0.0
+     */
+    native void freePerson(long handler);
+}
+class WeakGlobalReferenceTest {
+    static WeakGlobalReferenceTest globalWeakReferenceTest = new WeakGlobalReferenceTest();
+
+    /**
+     * 测试在JVM中使用JNI创建的对象全局弱引用
+     * @description:
+     * @author: 杨逸
+     * @data:2026/03/05 21:06:10
+     * @since 1.0.0
+     */
+    static void test(){
+        //获取全局弱引用的句柄
+        long personHandler = globalWeakReferenceTest.getPersonHandler();
+
+        //根据句柄获取全局引用对象
+        Person person = globalWeakReferenceTest.getPerson(personHandler);
+        System.out.println("person.getName() = " + person.getName());
+        System.out.println("person.getAge() = " + person.getAge());
+        System.out.println(person);
+        //释放全局弱引用
+        globalWeakReferenceTest.freePerson(personHandler);
+    }
+
+    /**
+     * 测试JNI创建的对象全局引用是否会被JVM垃圾回收
+     * @description:
+     * @author: 杨逸
+     * @data:2026/03/05 21:06:34
+     * @since 1.0.0
+     */
+    static void testJVMGC(){
+        while (true){
+            globalWeakReferenceTest.getPersonHandler();
+        }
+    }
+    /**
+     * 在JNI中创建一个全局引用,并返回句柄
+     * @return long 全局弱引用的句柄
+     * @description:
+     * @author: 杨逸
+     * @data:2026/03/04 21:29:12
+     * @since 1.0.0
+     */
+    native long getPersonHandler();
+
+    /**
+     * 根据句柄获取全局弱引用对象
+     * @param handler 句柄
+     * @return {@code Person } 全局引用弱对象
+     * @description:
+     * @author: 杨逸
+     * @data:2026/03/04 21:30:09
+     * @since 1.0.0
+     */
+    native Person getPerson(long handler);
+
+    /**
+     * 释放JNI创建的全局弱引用
+     * @param handler 句柄
+     * @description:
+     * @author: 杨逸
+     * @data:2026/03/04 21:30:38
+     * @since 1.0.0
+     */
+    native void freePerson(long handler);
+}
+class Person{
+    private String name;
+    private int age;
+
+    public Person(String name, int age) {
+        this.name = name;
+        this.age = age;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public int getAge() {
+        return age;
+    }
+
+    public void setAge(int age) {
+        this.age = age;
+    }
+
+    @Override
+    public String toString() {
+        return "Person{" +
+                "name='" + name + '\'' +
+                ", age=" + age +
+                '}';
+    }
+}