关于oom:GC overhead limit exceeded问题的分析与疑问

一、背景

应用运维人员通过granfna监控软件发现某主机内存在某一时刻内存使用率达到了90%以上,应用系统部分业务收到影响。此时应用人员通过应用日志查看,在异常期间,出现大量的out of memory:GC overhead limit exceeded的错误。找到应用厂商进行分析后,得出结论,告知是我们的应用启动参数maxPermSize设置过小导致(该参数设置大小为1G),需要增加-XX:MaxPermSize的大小。

二、基本概念了解

经过资料查询,在java应用启动参数中通常我们会调整几个参数:-Xms,-Xmx,-XX:PermSize,-XX:MaxPermSize;两组参数中分别代表了堆内存大小限制和非堆内存大小限制;堆内存是运行时数据区域,所有类实例和数组的内存均从此处分配,主要分为年轻代(Young Generation)、老年代(Old Generation);对内存存放的是对象,垃圾收集器就是收集这些对象,然后根据GC算法回收。非堆内存用,属于永久代,也称为方法区,存储程序运行时长期存活的对象,比如类的元数据、方法、常量、属性等。在JDK1.8版本,是以MetaSpace表示永久代;

因此,我认为堆内存较为活跃,会根据应用的使用在堆内存中创建新的对象,而由于堆内存的大小有限(设置了参数进行限制),则会有GC垃圾回收机制对堆内存中的释放对象进行回收,而当Java进程花费98%以上的时间执行GC,但只恢复了不到2%的内存,且该动作连续重复了5次,就会抛出java.lang.OutOfMemoryError:GC overhead limit exceeded错误。简单地说,就是应用程序已经基本耗尽了所有可用内存,GC也无法回收

而非堆内存则相对较为静止,在应用启动初期就会根据应用的需求将class等相关信息加载到该部分内存中。而当我们在进行应用启动的时候则会加载大量的class,如果此时永久代的空间不足,那么可能会出现out of memory:Permgen space的问题。

三、疑问

如果按照堆内存和非堆内存的概念来讲,应用厂商告知我们的结论和处理方式是不是就是不正确的呢?在永久代中,是不是不存在gc的回收?-XX:MaxPermSize的参数增大能解决我们的out of memory:GC overhead limit exceeded错误么?欢迎各位中间件专家大佬以及开发大佬踊跃讨论,帮忙解惑

猜你喜欢

转载自blog.csdn.net/wx370092877/article/details/130705830