Java 垃圾回收器 - 它何时收集?

2022-08-31 15:44:11

是什么决定了垃圾回收器何时实际收集?它是在一定时间之后还是在一定量的内存用完之后发生的?还是有其他因素?


答案 1

当它确定是时候运行时,它将运行。分代垃圾回收器中的常见策略是在第 0 代内存分配失败时运行收集器。也就是说,每次分配一小块内存(大块通常直接放入“较旧”的几代中)时,系统都会检查 gen-0 堆中是否有足够的可用空间,如果没有,它将运行 GC 以释放空间以使分配成功。然后,旧数据被移动到第 1 代堆,当空间耗尽时,GC 会对该堆运行一个集合,将存在时间最长的数据升级到第 2 代堆,依此类推。因此,GC不只是“运行”。它可能只在gen-0堆上运行(大多数集合都会这样做),或者如果它真的必须释放大量内存(这是很少需要的),它可能会检查每一代)。

但这远非一的策略。并发 GC 在后台运行,在程序运行时进行清理。某些 GC 可能作为每个内存分配的一部分运行。增量收集器可能会这样做,每次分配内存时扫描几个对象。

垃圾回收器的全部意义在于,它应该只做自己的事情,而不需要用户的任何输入。所以一般来说,你不能,也不应该预测它什么时候会运行。

我相信Suns JVM不久前获得了一代GC(也许是v1.6?我已经很久没有编写Java代码了,所以不确定这一点,但我记得不久前我很惊讶,当时新版本的卖点之一是“代际GC”。尤其是因为 .NET 从第 1 天起就有了。

其他JVM当然可以自由选择他们喜欢的任何策略。

编辑:上面关于Java和代际GC的部分是不正确的。有关更多详细信息,请参阅下文:

1.0 和 1.1 虚拟机使用标记扫描收集器,它可以在垃圾回收后对堆进行分段。从 Java 1.2 开始,虚拟机切换到了分代收集器,它具有更好的碎片整理行为(请参阅 Java 理论和实践:垃圾回收和性能)。

所以Java实际上有一代GC很长一段时间。Java 6 中的新增功能是 Java 6u14 中提供的垃圾优先垃圾回收器 (G1)。根据声称在1.6.0_14中发布的文章默认情况下不启用它。并行收集器仍然是默认的 GC,并且是常见家庭使用中效率最高的 GC。G1 旨在作为并发收集器的替代方法。它旨在提高可预测性,并通过内存区域设计实现快速分配。


答案 2
  • 这取决于程序JIT的编译方式。
  • 从外面看,我们无法确定它何时会运行。
  • 它遵循一些依赖于该特定GC的算法。
  • Java 虚拟机在客户端计算机上运行,如果 Windows 缺省值为 4GB,则具有一些虚拟内存。它还取决于该特定时间的可用虚拟内存。

您可以尝试这个小程序来检查GC的行为

public class GCTest {

   final int NELEMS = 50000;

   void eatMemory() {

      int[] intArray = new int[NELEMS];

      for (int i=0; i<NELEMS; i++) {
        intArray[i] = i;
      }

   }

   public static void main (String[] args) {

      GCTest gct = new GCTest();

      // Step 1: get a Runtime object
      Runtime r = Runtime.getRuntime();

      // Step 2: determine the current amount of free memory
      long freeMem = r.freeMemory();
      System.out.println("free memory before creating array: " + freeMem);

      // Step 3: consume some memory
      gct.eatMemory();

      // Step 4: determine amount of memory left after consumption
      freeMem = r.freeMemory();
      System.out.println("free memory after creating array:  " + freeMem);

      // Step 5: run the garbage collector, then check freeMemory
      r.gc();
      freeMem = r.freeMemory();
      System.out.println("free memory after running gc():    " + freeMem);
   }
}

可能的输出 -- 在您的案例中可能有所不同

free memory before creating array: 4054912
free memory after creating array:  3852496
free memory after running gc():    4064184

http://www.devdaily.com/java/edu/pj/pj010008/ 查看此链接