在 Java 里,触发垃圾回收(GC)的方式多种多样:
代码层面触发
1. 调用 System.gc()
或 Runtime.getRuntime().gc()
在 Java 代码中,可以调用 System.gc()
或者 Runtime.getRuntime().gc()
方法来建议 JVM 进行垃圾回收。不过要注意,这仅仅是一个建议,JVM 不一定会立刻执行 GC 操作。示例代码如下:
public class TriggerGCExample {
public static void main(String[] args) {
System.gc();
// 或者使用 Runtime.getRuntime().gc();
}
}
2. 动态生成大量类
如果程序在运行过程中动态生成大量的类,可能会使元空间(Java 8 及以后版本)或永久代(Java 7 及以前版本)空间不足,从而触发 Full GC 来回收无用的类信息。例如使用 CGLIB 或 Java 反射动态生成类:
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
interface SampleInterface {
void sampleMethod();
}
public class DynamicClassGeneration {
public static void main(String[] args) {
for (int i = 0; i < 10000; i++) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(Object.class);
enhancer.setInterfaces(new Class[]{SampleInterface.class});
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
return proxy.invokeSuper(obj, args);
}
});
enhancer.create();
}
}
}
命令行工具触发
1. jcmd
命令
jcmd
是 JDK 提供的一个多功能命令行工具,可用于向正在运行的 Java 进程发送诊断命令。使用以下命令能触发指定 Java 进程的 GC:
jcmd <pid> GC.run
其中,<pid>
是 Java 进程的 ID,可通过 jps
命令获取。
2. jmap -histo:live
命令
jmap -histo:live <pid>
命令会触发一次 Full GC。该命令用于输出堆中存活对象的统计信息,为了只统计存活对象,JVM 会先进行一次 Full GC 回收掉可回收的对象。
图形化工具触发
1. JConsole
- 启动方式:在终端输入
jconsole
命令启动。 - 操作步骤:选择要监控的 Java 进程,切换到“内存”选项卡,点击“执行 GC”按钮,尝试触发垃圾回收。
2. VisualVM
- 启动方式:在终端输入
jvisualvm
命令启动。 - 操作步骤:选择要监控的 Java 进程,切换到“监视”选项卡,点击“执行垃圾回收”按钮,尝试触发垃圾回收。
因 JVM 内存状况触发
1. 新生代空间不足
当新生代(如 Eden 区)没有足够的空间来分配新对象时,会触发 Minor GC(新生代垃圾回收)。例如,不断创建新对象可能会导致新生代空间不足:
import java.util.ArrayList;
import java.util.List;
public class YoungGenGCTrigger {
public static void main(String[] args) {
List<byte[]> list = new ArrayList<>();
while (true) {
list.add(new byte[1024]);
}
}
}
2. 老年代空间不足
当老年代没有足够的空间来容纳从新生代晋升过来的对象,或者直接在老年代分配大对象时空间不足,就会触发 Full GC。
3. 元空间不足
从 Java 8 开始,元空间用于存储类的元数据信息。当元空间满时,会触发 Full GC 来回收元空间中的无用类信息。
垃圾回收器特定情况触发
不同的垃圾回收器在某些特定情况下会触发 GC:
- CMS(Concurrent Mark Sweep):在进行并发标记过程中,如果发现老年代空间不足,会触发 Full GC 并使用 Serial Old 收集器进行垃圾回收。
- G1(Garbage First):当 G1 垃圾回收器的 Mixed GC 无法及时回收内存,导致堆内存使用率达到一定阈值时,会触发 Full GC。