安全点
Java应用程序中有两个逻辑线程组:
- 应用程序线程执行应用程序逻辑
- 执行GC的线程
在执行诸如堆压缩之类的操作时,GC线程会四处移动一些对象,并且这些对象不能被任何应用程序线程使用,因为它们的物理位置可能会发生变化。 这导致所谓的世界停顿。
停止世界(STW)暂停是指所有应用程序线程均已停止。 它们对Java应用程序性能具有最大的影响之一。 GC调整背后的基本概念是最大程度地减少这些停顿。 即使有GC算法之间的一些差异, 年轻一代 (小GC) 的收集过程中所有的人都停止了世界的停顿。
但是,应用程序线程无法随时停止。 这就是安全点起作用的地方。 安全点的以下定义来自HotSpot词汇表 :
程序执行期间的一点,所有GC根都是已知的,并且所有堆对象的内容都一致。 从全局角度来看,GC可以运行之前,所有线程都必须在安全点处阻塞。
从本质上讲,安全点是指JVM处于可以被其他线程(尤其是GC线程)安全地查看和操作的状态时的执行点。
使用安全点时,GC并非仅停下来进行暂停。 它们还可以在代码取消优化 ,热插拔或刷新代码缓存期间使用。
根据Peter Lawrey的说法 ,JVM放置安全点的位置没有特别的规定。 它可能因Java版本而异,但是Internet上的一些消息来源声称它通常在调用返回或JIT编译的代码从循环返回后发生。
跟踪安全点时,有几个标记可能非常方便:
-XX:+PrintGCApplicationStoppedTime
–打印所有安全点的暂停时间(不仅是GC的)
输出将如下所示:
- Application time: 0.2410613 seconds
- Total time for which application threads were stopped: 0.0511005 seconds
-XX:+PrintSafepointStatistics
–XX:PrintSafepointStatisticsCount=1
上面的标志打印出触发暂停的操作的名称以及一些其他信息(例如,事件发生时停止的线程数和时间戳)。
所有这些标志将信息打印到标准输出,而不是GC日志。