【问题标题】:Java GC safepointJava GC 安全点
【发布时间】:2023-03-31 18:45:02
【问题描述】:

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

【问题讨论】:

  • 不过,除了原生调用之外,我找不到一个例子来说明什么是安全点,什么不是。也许它定义不明确,但令人沮丧。
  • 检查了一个相关示例和错误报告here

标签: java garbage-collection


【解决方案1】:

safepoint 的确切定义和实现从一个 VM 实现更改为另一个,但考虑到 Hotspot VM,您可以在以下位置找到一个很好的定义:Safepoints in HotSpot JVM

HotSpot glossary 说:

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

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

检查需要安全点的 VM 操作列表:Safety First: Safepoints

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

【讨论】:

    【解决方案2】:

    很遗憾,这是一个定义不佳的字段。 JVM 在决定时放置安全点,但没有具体说明何时。 Java 的下一个版本/更新可能会有所不同。在某些情况下,例如 Unsafe.copyMemory() 没有安全点,但您无法确定安全点将放置在哪里。

    【讨论】:

    • 嗯,但这是一个本地调用,我一直认为本地调用是一个安全点……也就是说,进入本地并留在那里是安全的,但不能回到 Java 代码(如果 GC 正在进行中)。
    • @Cowboy 正确,但 copyMemory 可以是任意长度,因此复制的时间越长,到达安全点的时间就越长。
    • @PeterLawrey Unsafe 可以有无限长度;这就是为什么 Bits 一次最多只能复制 1MB;这是为了允许或安全点 AFAIK
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-08-18
    • 2019-08-16
    • 1970-01-01
    • 2012-11-18
    • 1970-01-01
    • 2023-03-31
    • 1970-01-01
    相关资源
    最近更新 更多