Java堆内存富余却疯狂FullGc问题排查

来源:互联网 发布:米多大数据引擎系统 编辑:程序博客网 时间:2024/06/04 00:27

    刚上线了一个新的应用集群,第二天和第三天收到了应用FullGc超过阈值的报警短信。但是观察报警Java实例的jvm监控,堆内存仅仅用了1G多一点,还富余近700M。很困惑,剩余这么多内存没被使用,那么说明老年代内存是充足的才对啊!

    同事提醒我是不是申请了什么大对象,诚然,老年代只会有两种类型的对象,1,多次Minor Gc中存活的小对象,2,大对象,即超过了PretenureSizeThreshold这个阀值直接分配到老年代的对象。一般疯狂Full Gc的原因就是程序申请大对象导致的。这回还是跟大对象有关吗?

    针对报警的实例进程执行jstat -gcutil 命令,拿到了这个java进程的内存个个代的使用百分比。

    发现P的使用率是98%,P,即 Permanent Generation,永久代。也就是说永久代的使用率已经超过了98%。于是问题明了了。FullGc,大家很容易想到的是Old Generation内存爆了导致的!但是这不是唯一的条件,永久代内存回收也是归FullGc管的!于是强烈建议我们的监控界面添加永久代的监控。永久代能回收什么呢?一,废弃的字符串常量,二,不再被引用的class对象。

    再针对这个实例执行  jstat -gccapacity pid 命令,发现这个实例的永久代仅仅给了82M。82M意味着什么,永久代的默认堆内存大小。

    果断添加JVM的永久代参数,-XX:PermSize=512M -XX:MaxPermSize=512M -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/export/Logs/im.**.com/ 。顺便加上堆内存OOM的自动dump参数。

1 0
原创粉丝点击