Java G1 GC-大型后台I/O导致JVM无响应-暂停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

我们有一个java应用程序,它几乎需要实时响应。但我们也看到了长达8秒的暂停

特殊运行条件:

  • 在某些时间间隔内,应用程序会将大小高达1.5G的大型数据快照序列化到磁盘(SSD)中
  • 偶尔,m/c中的其他共存进程会发生一些重背景I/O 我们所服务的,这个大型序列化写入发生的时间间隔内,如果碰巧GC启动,它会导致6到8秒的巨大暂停,JVM处于完全无响应/冻结状态

    JFR记录显示

  • 除正在写入磁盘的线程外,所有线程都处于驻车/等待/睡眠状态
  • G1 GC大约需要200毫秒才能完成GC
  • 从GC日志:2018-09-05T18:23:40.277+0000:39892.345:停止应用程序线程的总时间:8.3785112秒,停止线程的时间:8.3765855秒

    Java版本: java版本“1.8.0_181” Java(TM)SE运行时环境(build 1.8.0_181-b25) Java热点(TM)64位服务器VM(构建25.181-b25,混合模式)

    问题:

  • 当GC和后台I/O同时发生时,为什么会有这样8秒的非GC JVM暂停
  • 如何克服这个巨大的停顿

  • 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没有安全点不能取消。没有这样的选择。