目录
在 Java 中,垃圾收集(GC)并不是任意时刻都能进行的。它必须要当 Java 程序到达相关的安全点之后,才能够进行垃圾收集。
一、安全点的概念
安全点是程序执行的某些特定位置。在这些位置进行 GC 时,可以让程序的状态是可知的或者一致的。例如,当程序正在操作内存,操作到一半时不能进行 GC,必须等这一次操作内存的所有动作完成后,比如一条正在写内存的指令写完后,在某一个时刻暂停线程,进行 GC 垃圾收集。
二、安全点的设置
- 方法调用:每次方法调用的时候是一个潜在的可以成为安全点的位置。因为在方法调用之前,程序没有在做一些如内存操作之类的动作,此时暂停程序进行 GC 问题不大。
- 循环回跳:在长时间的循环中间,可能会插入安全点的检查。当线程执行到循环回跳的位置时,这个位置有可能成为安全点。
- 异常处理:在处理异常的时候,也有可能检查程序是否到达安全点,这个位置也可能成为一个安全点。
三、代码示例
以下是一个简单的代码示例,并标示出可能存在的安全点:
public class GCDemo {
public static void main(String[] args) {
int sum = 0;
for (int i = 0; i < 100; i++) {
sum += i;
}
}
}
在这个代码中,循环回跳的位置(即sum += i;
执行完后准备进入下一次循环的位置)有可能成为一个安全点。当线程执行到这个位置,如果 JVM 需要进行 GC,它会等到所有线程都走到安全点后才触发真正的 GC 执行。另外,方法结束的时候也可以成为一个安全点,因为此时线程没有再做其他操作。
总之,在进行 GC 之前,JVM 会检查所有线程是否到达安全点,如果所有线程都到达了安全点,才会开始进行 GC,这样可以保证线程的状态是可知的、一致的,避免程序出现 bug。