Dhi*_*osh 5 java garbage-collection g1gc pause
我们有一个几乎需要实时响应的 Java 应用程序。但我们也看到了长达 8 秒的停顿。
特殊运行条件:
我们正在观察的是,在这个大型序列化写入发生的间隔期间,如果 GC 偶然启动,它会导致 6 到 8 秒的巨大暂停,JVM 处于完全无响应/冻结状态。
从 JFR 记录可以看出,
来自 GC 日志:2018-09-05T18:23:40.277+0000: 39892.345:应用程序线程停止的总时间:8.3785112秒,停止线程花费:8.3765855 秒
Java 版本:java 版本“1.8.0_181”Java(TM) SE 运行时环境(构建 1.8.0_181-b25)Java HotSpot(TM) 64 位服务器 VM(构建 25.181-b25,混合模式)
问题:
JFR 文件:https : //www.filehosting.org/file/details/756217/Run.jfr
你的问题不在于 GC,而在于 JVM Stop-The-World 机制 - safepoints。JVM 等待所有线程停放在安全点上,然后再开始 GC 相关工作。
如果您的 Java 代码使用内存映射文件,您可能需要将其替换为常规 IO。内存映射(尤其是大量写入)对安全点机制影响很大。访问内存映射文件的线程可能会被等待写入/读取内存页面的操作系统阻塞。如果此时触发 GC,则必须等待 IO 阻塞线程恢复并到达下一个安全点检查。
更新:说起来很简单,如果 Java 线程在RandomFile/ Channelread 方法上被阻塞,它不会阻止 JVM 安全点。但是,如果 Java 线程在对内存映射文件进行读/写操作时被阻塞,那么在线程解除阻塞之前,JVM 无法进入安全点。如果此类访问包含在循环中,它甚至可能会等到循环在某些条件下完成。
导致长时间“停止线程”的另一个问题可能是循环。如果您有带有 int 计数器的简单循环,JVM 会认为它“快”并且可能会忽略循环体内的安全点检查。
| 归档时间: |
|
| 查看次数: |
732 次 |
| 最近记录: |