今天线上爆出了 java.lang.OutOfMemoryError: PermGen space
当时吓尿了,怎么突然报永久代内存溢出,临时先加大了永久代内存,将启动参数改为:
-XX:PermSize=128m为 -XX:PermSize=256m
启动异常消失。
留了一台机器jvm参数为之前的,来观察问题。用 jstat命令查看发现惊人一幕
不得了永久代占了99.07%了,后来想到这个版本 加了个扫描包下class的工具,但是不确定是这个引起的。
于是 在启动参数上加了 -verbose:class , 打印加载类的信息 , 发现确实是我扫描包下面的所有无关类都被加载了,而且很多, 然后用jstat查看 永久代 已经90%多了。程序刚启动就是90%多,大部分都是 巨多的class被加载了。
最终断定 代码用到了扫描包,并调用了Class.forName() 将相关类都加载了进来,到达了永久代内存临界点,程序运行过程中如果在要加载常量和其它动态类,就没有内存了,导致报了线上内存溢出。
PermGen(永久代)
绝大部分 Java 程序员应该都见过 "java.lang.OutOfMemoryError: PermGen space "这个异常。这里的 “PermGen space”其实指的就是方法区。不过方法区和“PermGen space”又有着本质的区别。前者是 JVM 的规范,而后者则是 JVM 规范的一种实现,并且只有 HotSpot 才有 “PermGen space”,而对于其他类型的虚拟机,如 JRockit(Oracle)、J9(IBM) 并没有“PermGen space”。由于方法区主要存储类的相关信息,所以对于动态生成类的情况比较容易出现永久代的内存溢出。
更多JVM 内存划分 ,请详见这篇文章:
JVM - 运行时数据区 内存结构 详解githubs.xyz
强烈推荐一个走向Java架构师道路的博客
本文完~