JVM的GC执行时机与安全点

258 阅读4分钟

一、JVM的GC执行时机

JVM的GC并非在任何时刻都会发生。具体的触发时机与垃圾收集器的类型和设置等多因素有关。一般来说,例如在年轻代空间内存对象进行分代处理后,可能会执行Minor GC或Full GC。此外,有些GC机制可能会在系统空闲CPU资源时启动,有些则可能在内存消耗达到一定程度时启动。

以最常用的串行收集器Serial Collector为例,它采用单线程的方式进行垃圾回收,因此会“暂停”所有应用线程(也即STW,Stop The World)。而并行收集器Parallel Collector则是多线程进行的,它在垃圾回收时不需要暂停所有的应用线程。

二、安全点

安全点是GC执行时的一个特定位置--只有在这些特定的“安全点”,程序才能暂停下来开始GC。选择安全点对于GC的执行非常重要,因为如果安全点设置得过少可能使得GC的等待时间过长。

那么,如何确定安全点呢?简单来说,安全点的选取要保证程序的正确性。如果选择的位置不正确,可能会导致程序出现错误。例如,在执行某个操作的过程中被中断,就可能导致数据不一致的问题。

确定安全点的方法主要有两种:一种是通过“安全区域”来选择,另一种是通过程序的“特定位置”来选择。

  • 安全区域:JVM会分析代码,找出那些不可能被执行的代码区域,这些区域被称为“安全区域”。在GC执行时,只有当所有线程都到达了这些“安全区域”,才会暂停下来开始GC。这种方法的好处是不需要额外的处理,但是缺点是可能会导致GC的等待时间过长。

  • 特定位置:程序员可以在代码中显式地设置一些“安全点”,这些位置在GC执行时会被暂停。例如,可以在某个方法的开始和结束处设置安全点。这种方法的好处是可以精确控制GC的执行时机,但是缺点是需要额外的处理,并且如果设置的位置不正确,可能会导致程序出现错误。

三、

public class Test {
    private static final int _1MB = 1024 * 1024;
    private byte[] bigSize = new byte[2 * _1MB]; //分配2MB大小的数组
    public static void main(String[] args) {
       System.out.println("start");
      for (int i = 0; i < 100; i++) {
          new Test().createMegaBytes();
      }
      System.out.println("end");
   }
    private void createMegaBytes() {
        byte[] allocation1, allocation2, allocation3, allocation4;
        allocation1 = new byte[2 * _1MB];
        allocation2 = new byte[2 * _1MB];
        allocation3 = new byte[2 * _1MB];
        allocation4 = new byte[4 * _1MB]; //出现一次Minor GC
        try {
            Thread.sleep(50); //让其他线程运行并执行GC
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

在这个例子中,我们创建了大约80MB的对象,这可能会触发Minor GC。然后我们让主线程睡眠50毫秒,以便给其他线程运行并执行GC的机会。这就是一个典型的手动触发GC的例子。

四、

关于JVM如何选择安全点,其底层原理涉及到JVM的具体实现细节。

具体来说,JVM如何选择安全点涉及到JVM的具体实现细节,其中一个重要的环节是根节点枚举(Root set enumeration)。在进行垃圾回收时,JVM需要判断哪些对象是存活的,哪些对象是可以被回收的。目前主流的判断对象是否存活的算法有两种:引用计数算法和可达性分析算法。Java采用的是可达性分析算法来判断对象是否存活。

一般来说,JVM会选择一些程序中不太可能改变的区域作为安全点,比如方法调用、循环跳转等地方。当程序执行到这些位置时,JVM会检查是否有垃圾回收的需求。如果有,就会在这些位置上设置一个标志,表示这里是一个安全点。然后在垃圾回收过程中,只有当所有线程都到达了这些安全点时,才会真正开始垃圾回收。否则,垃圾回收器会等待直到所有线程都到达了安全点。