学习笔记

发布于 2021-12-07  801 次阅读


问题出现的原因

由于Parallel Scavenge收集器的自适应能力,在环境改变的情况下,新生代内配比动态变化至不合理的状态(反应在文章中则是 Eden 与 Survivor的比例为100:1:1)
在这种状态下,Eden 区中存活下来的对象会迅速填满 Survivor 区,而我们知道,Survivor 区存在的意义就是减少被送到老年代的对象,进而减少 Full GC 的发生,当 Survivor 区太小,Young GC后存活下来的对象太多,无法放入 Survivor 区的时候,这些对象会被直接转移到老年代去,从而会加快 Old 区的填满速度,触发 Full GC
很明显,如果 Eden 与 Survivor 的比例始终异常,那么会频繁触发Full GC(这也正是文中提到的问题出现的原因之一)
当然,我们需要考虑到的是,Eden 与 Survivor 的比例异常有多种情况,如:

1.Survivor 太小(即100:1:1),这种情况会频繁触发 Full GC(因为削弱了S 区的垃圾拦截能力)
2.Survivor 够大,可能正常,也可能有其他情况
...

对应到文中,即为前辈所提到的 环境 ,即 因为问题触发是在代码未发生变化的大前提下产生,与当前环境有直接关系,而环境是一个变量,It could be better, it could be worse,如果针对现状进行参数整改,可能也仅仅只能解决一时。

我对环境一词的理解

该项目在运行过程中状态的不断改变,就叫环境
因为我们无法完整的监控运行状态的改变,因此环境具有不确定性
而调整策略:部分机器配置调整,新生代收集器由Parallel Scavenge切换为ParNew(并行收集器,全程STP,停顿少,效率高,没有自适应功能,可以保证比例不变),是为了通过解决问题一:稳定Eden 与 Survivor 区内配比,减少环境的不确定性

后续优化的方向

通过模拟,监控,观察运行状态的规律,如峰值,波形等,确定一些参数,从而减少环境的不确定性

补充:-XX:PretenureSizeThreshold
-XX:PretenureSizeThreshold,设置大对象直接进入年老代的阈值。-XX:PretenureSizeThreshold只对串行回收器和ParNew有效,对ParallGC无效。默认该值为0,即不指定最大的晋升大小,一切由运行情况决定。
该参数对ParNEW收集器有效,如果我们能确定(规律也可)运行状态下的大对象的个数范围和大小,可以设置该参数,可避免年轻代里出现大对象,屡次躲过GC,在两个Survivor区域里来回复制多次之后才能进入老年代的情况,从而得到优化


她喜欢所以就做咯