jvm gc时对对象引用的判断

这是一段 GC 测试的代码:

public class GCTest {
    public static void main(String[] args) {
        Runtime runtime = Runtime.getRuntime();
        System.out.println("初始空闲内存:" + getFreeMemory(runtime.freeMemory()));

        ArrayList<Object> list = new ArrayList<>(10000000);
        ArrayList<Object> list2 = list;
        System.out.println("创建一个一千万大小的数组列表对象后,空闲内存:" + getFreeMemory(runtime.freeMemory()));

        for (int i = 0; i < 10000000; i++) {
            list.add(new Object());
        }
        System.out.println("给数组中每个位置添加一个对象后,空闲内存:" + getFreeMemory(runtime.freeMemory()));

        System.gc();
        System.out.println("手动调用 GC 后,空闲内存:" + getFreeMemory(runtime.freeMemory()));  

        list = null;
        System.gc();
        System.out.println("置数组对象为 null,手动调用 GC 后,空闲内存:" + getFreeMemory(runtime.freeMemory()));   

//        System.out.println(list2 == null);
    }

    public static long getFreeMemory(long freeMemory) {
        return freeMemory/1024/1024;
    }
}

System.out.println(list2 == null); 被注释掉以后的结果:

初始空闲内存:237
创建一个一千万大小的数组列表对象后,空闲内存:199
给数组中每个位置添加一个对象后,空闲内存:157
手动调用 GC 后,空闲内存:157
置数组对象为 null,手动调用 GC 后,空闲内存:338

注释去掉后的结果:

初始空闲内存:237
创建一个一千万大小的数组列表对象后,空闲内存:199
给数组中每个位置添加一个对象后,空闲内存:157
手动调用 GC 后,空闲内存:156
置数组对象为 null,手动调用 GC 后,空闲内存:144
false

可以看到注释前后,gc 回收是不一样的。

问题:list 和 list2 同时指向这一个数组对象,按跟搜索算法来讲,list 和 list2 都可以作为 GC roots,只要不是 list = null 和 list2 = null 同时发生,数组对象就不会被回收,那为什么上面第一种情况,只有 list = null,数组对象却被回收了呢?list2 还指向这块区域的啊。

阅读 2.2k
1 个回答

悬空的变量list2会在编译后被优化掉。
在注释掉的情况下,用Byte Code Viewer 反编译编译出来的class文件:

import java.util.ArrayList;

public class GCTest {
   public static void main(String[] var0) {
      Runtime var1 = Runtime.getRuntime();
      System.out.println("初始空闲内存:" + getFreeMemory(var1.freeMemory()));
      ArrayList var2 = new ArrayList(10000000);
      System.out.println("创建一个一千万大小的数组列表对象后,空闲内存:" + getFreeMemory(var1.freeMemory()));

      for(int var4 = 0; var4 < 10000000; ++var4) {
         var2.add(new Object());
      }

      System.out.println("给数组中每个位置添加一个对象后,空闲内存:" + getFreeMemory(var1.freeMemory()));
      System.gc();
      System.out.println("手动调用 GC 后,空闲内存:" + getFreeMemory(var1.freeMemory()));
      var2 = null;
      System.gc();
      System.out.println("置数组对象为 null,手动调用 GC 后,空闲内存:" + getFreeMemory(var1.freeMemory()));
   }

   public static long getFreeMemory(long var0) {
      return var0 / 1024L / 1024L;
   }
}

可以看到,这里已没有list2这个变量了。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题