问题描述
两系统间同步数据,因数据量较大,执行时间较长.数次执行后发现jvm占用内存较大,且长时间未释放. 排查代码,并未有全局引用.相关代码为局部变量,不存在引用未清空情况.
思路:
启动 visualVM 监控内存使用情况,模拟任务调度
- 第一个红色框,为任务调度开始,此时因内存使用较大,Eden Sapce (新生代)触发多次gc,之后 Old Gen(老年代) 内存使用增大.推测,因为任务较大,中途触发多次新生代GC,导致list对象进入老年代.
- 第二个红色框,再次触发GC后,新生代内存下降,老年代内未并未变化.新生代GC并未触发老年代GC,此时虽然对象已经没有引用,但是一直存在于老年代.
- 第三个红色框,手动触发full GC,新生代,老年代同时GC,内存释放.
小结
jvm的GC,针对新生代,老年代调度是分离的,比如执行很多次新生代GC,但是老年代一直没有GC.full GC会导致虚拟机暂停,在内存充足的情况下没有必要full GC.属于正常情况,不需要调整代码.或者可以调整老年代大小,更加频繁的触发full GC,不过这肯定不是你想要的.