OutOfMemoryError:PermGen space

JVM知识专栏JVM-火种,持续更新,喜欢请关注😍

    java.lang.OutOfMemoryError: PermGen spaces是指永久区内存溢出的错误,根据分代思想的垃圾回收策略,老年代和永久区的内存溢出都会导致系统卡死。内存溢出在本地开发环境和生产环境都是较为常见的错误,解决的方案大致可以分为两种:
一 适当调大jvm参数
    首先明确一下永久区是用于存储类信息、常量池、静态变量、JIT编译后的代码等数据,所以系统正常启动本身就是要占用永久区的,就算代码写的再牛逼、再高明,只要有业务逻辑就会占用永久区内存,这是属于jvm虚拟机的正常消耗。假如你的应用在类加载过程过程后正常就应该有200mb的对象创建到永久区,但是此时你设置的永久区最大容量是128mb,这个过程必然会导致内存溢出,这时候就直接扩大参数就行了,就不要去定位什么地方的代码导致了溢出,没有意义。
    在修改前先了解一个可视化工具visualvm。visualvm是jdk1.5后的版本中官方赠送的调试程序,虽然在官方文档中介绍这个工具仍处于测试阶段,但实际上这个工具已经十分成熟了,而且性能十分强悍,简单易用,建议大家深度挖掘一下。本文推荐通过visualvm工具去查看实时的JVM状况,从而判断做的修改是否有效,使用其他工具排查也是同样的道理。windows环境中直接到jdk安装目录bin文件夹下双击jvisualvm.exe打开,或者在cmd下输入jvisualvm回车。也可以通过远程配置监控linux环境下的tomcat。我调试的是本地tomcat。
在这里插入图片描述
    图中箭头指向的就是本次测试的tomcat,双击tomcat即可看到这个应用的详细信息以及内存占用情况。点击’工具’---->‘插件’----'可以插件’中下载Visual GC,Visual GC工具可以通过可视化窗口查看实际内存使用情况。如果可下载工具中没有Visual GC。可以先去pluginscenters下载对应工具到本地,再从已下载中添加到工具中
-在这里插入图片描述
    现在我们模拟一个以及发生了‘java.lang.OutOfMemoryError: PermGen spaces’情况的tomcat。我设置了的参数内容为-XX:PermSize=50m -XX:MaxPermSize=50m,启动tomcat果然出现了内存溢出报错。
在这里插入图片描述
    打开Visual GC窗口,通过观察左侧的柱状图可以看到perm已经满了。Old和Eden区的内存使用情况属于合理的情况。右下方的内存详细介绍中展示的perm区参数确实是-XX:PermSize=50m -XX:MaxPermSize=50m。
在这里插入图片描述
    问题复现完成,我们就要动手解决了。翻了网上诸多版本的解决方案后得出了以下几种修改方式
解压缩版tomcat修改tomcat\bin\Catalina.bat文件中的内存参数(解压缩和安装版本区别为bin下面有没start文件,有为解压缩版本)。具体修改为: 找到setlocal这一行,然后在这一行的上面一行,插入一行,内容如下

set "JAVA_OPTS=-server -Xms1024m -Xmx2048m  
		-XX:PermSize=256m
		-XX:MaxPermSize=512m"

在这里插入图片描述
安装版本tomcat修改tomcat\bin\Tomact7w.exe中的Java options参数,修改方式为:在Java options中加入

-XX:PermSize=256m
-XX:MaxPermSize=512m

在这里插入图片描述
myeclipse中修改jdk下的Optional Java VM arguments内存参数,修改方式为:打开Myeclipse–>Servers–>Tomcat–>Tomcat–>jdk修改Optional Java VM arguments参数: -XX:PermSize=256m -XX:MaxPermSize=512m
在这里插入图片描述
myeclipse中修改Run Configurations中的Arguments内存参数,tomcat右键打开Run Configurations配置中心。在Arguments的页签下编辑VM arguments,加入 -XX:PermSize=128m -XX:MaxPermSize=256m
在这里插入图片描述
    通过对多种情况的测试后得出Myeclipse中启动Tomcat时,myeclipse中Server->Tomcat中的的jdk配置的优先级大于tomcat配置的优先级。通过对参数调优后我们再次启动项目,可以看到优化后的实时内存使用情况。在概述栏可以看到优化后的参数为256、512
在这里插入图片描述
Visual GC的实时情况
在这里插入图片描述
    内存使用情况已经正常了,后台也没有内存溢出.本文中使用的参数都为256、512,大家可以按照自己的实际情况进行调配。不建议调的太大,满足项目运行需要即可。
二 允许GC回收永久区
第一方案针对的是永久区实际占用容量是在合理范围内的情况,另一种情况就是系统确实存在不合理的代码,或者调用的jar存在大量创建对象的情况,我们为模拟这种场景先上一段动态创建bean的代码

import org.springframework.cglib.beans.BeanGenerator;

for(int i = 0 ; 1 <1000000  ; i++){
		try {
			BeanGenerator generator = new BeanGenerator();
			generator.addProperty("PermGenOOM"+i,  Class.forName("java.io.File"));
			generator.create();
			System.out.println("创建第"+i+"个Bean对象");
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
}

运行前的类装载数据为9041,运行循环创建代码后的类装载数量为92300(这个功能可以帮助我们衡量永久区溢出是不是有异常代码,假如以前总装载数很小,最近装载数量变的很大,就可能是最近更新的代码有问题)
在这里插入图片描述
在这里插入图片描述
运行代码后永久区溢出
在这里插入图片描述
在jvm参数中添加允许回收永久区的参数,只有CMS收集器支持,它会把系统中不再被调用的方法进行回收,缩减永久区内存占用。第一个参数表示使用CMS收集器,第二个参数表示允许对永久区进行垃圾回收。但是这个参数只针对不再调用的方法,如果在发生回收时某些类的应用存在就不会被回收。

-XX:+UseConcMarkSweepGC -XX:+CMSClassUnloadingEnabled
  • 6
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值