君子以自强不息。
分配时发生回收
在快速分配和慢速分配内存不足时,就可能发生垃圾回收,回收之后再继续分配。可能会触发3种不同类型的 GC:
- 新生代回收
- 混合回收
- Full GC
外部调用的回收
常见有两种外部调用情况可以激活垃圾回收:
-
外部显式调用 system.gc 触发。一般来说,如果我们没有设置 DisableExplicitGC(默认为 false),表示可以接受这个函数显式地触发 GC。这个时候触发的 GC 都是 Full GC,但是如果设置了 ExplicitGCInvokesConcurrent,则表示可以进行并发的混合回收。
-
如果和 JNI 交互,JNI 代码进入了临界区(比如 JNI 代码为了优化性能,提供了一个函数 jni_GetPrimitiveArrayCritical/jni_GetStringCritical 用于直接访问原始内存数据,但是为了保证安全必须使用 GCLocker 进行加锁。当加锁后发生了 GC 请求,此时 GC 会被延迟,直到 GCLocker 执行了 unlock 会重新补一个 GC),而且设置了 GCLockerInvokesConcurrent,则可以进行并发混合回收,如果没有设置则可能启动新生代回收。实际上 JVM 还提供了 WhiteBox API 用于 JVM 内部测试,也可以执行 GC,因此也会触发新生代回收、FGC 等。
总结
- 在分配对象时如果内存不足,就会触发垃圾回收。
- 外部显式地调用回收的方法,如在 Java 代码中调用 system.gc() 进入回收。