Java G1 GC-大型后台I/O导致JVM无响应-暂停8秒
我们有一个java应用程序,它几乎需要实时响应。但我们也看到了长达8秒的暂停 特殊运行条件:Java G1 GC-大型后台I/O导致JVM无响应-暂停8秒,java,garbage-collection,pause,g1gc,Java,Garbage Collection,Pause,G1gc,我们有一个java应用程序,它几乎需要实时响应。但我们也看到了长达8秒的暂停 特殊运行条件: 在某些时间间隔内,应用程序会将大小高达1.5G的大型数据快照序列化到磁盘(SSD)中 偶尔,m/c中的其他共存进程会发生一些重背景I/O 我们所服务的,在这个大型序列化写入发生的时间间隔内,如果碰巧GC启动,它会导致6到8秒的巨大暂停,JVM处于完全无响应/冻结状态 JFR记录显示 除正在写入磁盘的线程外,所有线程都处于驻车/等待/睡眠状态 G1 GC大约需要200毫秒才能完成GC 从GC日志:2018
JFR文件:您的问题不在GC中,而是JVM停止了世界机制-。JVM等待所有线程停在safepoint上,然后再开始GC相关的工作 如果Java代码使用的是内存映射文件,则可能需要将其替换为常规IO。内存映射(尤其是写重)在safepoint机制中的作用不好。正在等待写入/读取内存页的操作系统可能会阻止线程访问内存映射文件。若GC在此时刻被触发,它将不得不等待IO阻塞线程恢复并到达下一个安全点检查 更新:简单地说,如果Java线程在
RandomFile
/Channel
读取方法上被阻塞,它不会阻止JVM safepoint。但如果Java线程在内存映射文件上的读/写操作被阻塞,JVM将无法进入安全点,直到线程被解除阻塞。若这种访问被包装在循环中,它甚至可能在某些条件下等待循环完成
另一个导致长时间“停止线程”的问题可能是循环。如果你有简单的带有int计数器的循环,JVM认为它是“快速”的,并且可以省略循环体中的安全点检查。谢谢阿列克谢。您提到“内存映射(尤其是写重)对安全点机制的影响很糟糕”。请你再详细说明一下好吗。常规IO与内存映射相比有多大帮助?谢谢Alexey。非常感谢您的回复。这就解释了问题所在,我们在写操作中使用了MappedByteBuffer。有没有一种方法可以告诉JVM,如果在X毫秒内没有达到安全点,那么就取消安全点操作,我是说任何JVM调优参数?@DhimanGhosh没有安全点不能取消。没有这样的选择。