关键词
-
垃圾回收gc
gc参考:https://blog.csdn.net/xyc1211/article/details/88594745 -
削峰填谷Peak cut
-
Java的安全点 safepoint
safepoint是一个记录指令OopMap(指针对象表 ordinary object pointer Map)的位置
程序执行到了safepoint才能暂停执行, 让gc去回收内存垃圾 -
可数循环(Counted Loop)、不可数循环(Uncounted Loop) 对safepoint的影响
可数循环的时候 无法进入safepoint
-
jvm 执行native方法 对safepoint的影响
执行native 会进入safepoint
原因:native方法 是 jvm之外的代码。jvm调用外部的代码前,必须记录自身的状态 才能在native方法返回后继续执行,所以必须加入safepoint
背景
jvm虚拟机为了避免 safepoint过多带来过重的负担,有些代码是不给设置safepoint的
例如用int类型索引的for循环: 认为int类型比较小 属于 可数循环(Counted Loop),那循环次数不会很长,就不设置safepoint了
如果在没有safepoint的代码段做了大量耗时的操作,这段时间不会进行GC,一直等到出现了safepoint才会 触发一次长时间的GC,导致程序长时间STW
解决方案
- 思路:
对GC 打散运行,削峰填谷,运行多次短 GC,从而避免长GC,防止长时间的垃圾收集
方案1:人工加入safepoint
对于没有safepoint的代码段 ,每隔一段就执行 native 方法,人工触发进入Safepoint
//Thread.sleep(0) 是JNI调用,会进入safepoint
Thread.sleep(0)
方案2:无safepoint代码改为有safepoint的
可数循环(Counted Loop)改为 不可数循环(Uncounted Loop)
就是循环的索引 从 int 修改为 long。