Java GC安全点

当垃圾收集器在清理未引用的对象之前冻结应用程序线程时,所有线程都需要在执行时处于“安全点”。 我发现了大量描述安全点概念的文章,但很少有例子。 将安全点置于典型Java方法中的哪个位置?为什么? 更重要的是,安全点何处才能发生?

安全点的确切定义和实现从一个VM实现更改为另一个VM实现,但考虑到Hotspot VM,您可以在HotSpot JVM中找到一个很好的定义: Safepoints 。

HotSpot词汇表说:

程序执行期间的所有GC根已知并且所有堆对象内容一致的点。 从全局的角度来看,所有线程必须在GC运行之前在安全点阻塞。

通常,安全点通过JVM向方法中注入安全点检查来实现,大多数调用站点都符合安全点 – 当到达安全点检查时,线程将检查是否需要安全点(例如,是否安排了FullGC),如果是,则线程块。 当VM中的所有线程阻塞时,您已到达安全点,VM中的所有对象都可以完全访问。 然后,执行请求安全点的VM操作(例如,FullGC),之后恢复线程。

检查需要安全点的VM操作列表: 安全第一:安全点 。

您可以使用-XX:+PrintSafepointStatistics –XX:PrintSafepointStatisticsCount=1来研究Hotspot中的安全点行为-XX:+PrintSafepointStatistics –XX:PrintSafepointStatisticsCount=1

不幸的是,这是一个很糟糕的领域。 JVM在决定时会放置安全点,但是没有规定什么时候。 下一个Java的一个版本/更新可能不同。 在某些情况下,例如Unsafe.copyMemory()没有安全点,但您无法确定安全点的放置位置。