JVM记一次PermGen space内存溢出实战案例


学习前先看下内存溢出的分类:https://blog.csdn.net/ZGL_cyy/article/details/126305144

在这里插入图片描述

1 永久代背景介绍

永久代是用于存放静态文件,如Java类、方法等。
持久代对垃圾回收没有显著影响,但是有些应用可能动态生成或者调用一些class,
例如Hibernate]等,在这种时候需要设置一个比较大的持久代空间来存放这些运行过程中新增的类

永久代中一般包含:
	-1 类的方法(字节码...)
	-2 类名(Sring对象)
	-3 .class文件读到的常量信息
	-4 class对象相关的对象列表和类型列表 (e.g., 方法对象的array).
	-5 JVM创建的内部对象
	-6 JIT编译器优化用的信息

1.1 永久代与方法区

永久带是方法区的一种实现,其中存储类模板信息,常量以及静态变量。

1.2 永久代的回收机制

hotspot的方法区存放在永久代中,因此方法区被人们称为永久代。永久代的垃圾回收主要包括类型的卸载和废弃常量池的回收。当没有对象引用一个常量的时候,该常量即可以被回收。而类型的卸载更加复杂。必须满足一下三点,该类型的所有实例都被回收了,该类型的ClassLoader被回收了,该类型对应的java.lang.Class没有在任何地方被引用,在任何地方都无法通过反射来实例化一个对象

2 内存溢出日志分析

在这里插入图片描述
在这里插入图片描述
分析日志的话没有具体的哪行代码溢出,看着好像就是因为夹在的jar包过多,然后永久代不够了。

2.1 PermGen space

PermGen space的全称是Permanent Generation space,是指内存的永久保存区域,这块内存主要是被JVM存放Class和Meta信息的,Class在被Loader时就会被放到PermGen space中,它和存放类实例(Instance)的Heap区域不同,GC(Garbage Collection)不会在主程序运行期对PermGen space进行清理,所以如果你的应用中有很多CLASS的话,就很可能出现PermGen space错误,这种错误常见在web服务器对JSP进行pre compile的时候。如果你的WEB APP下都用了大量的第三方jar, 其大小超过了jvm默认的大小(4M)那么就会产生此错误信息了。

2.2 常规解决方法配置参数

虽然说调参解决了一时,解决不了一世。

手动设置MaxPermSize大小,如果是linux系统,修改TOMCAT_HOME/bin/catalina.sh,如果是windows系统,修改TOMCAT_HOME/bin/catalina.bat,

在“echo “Using CATALINA_BASE: $CATALINA_BASE””上面加入以下行:

JAVA_OPTS="-server -XX:PermSize=1024M -XX:MaxPermSize=1024m

建议:将相同的第三方jar文件移置到tomcat/shared/lib目录下,这样可以达到减少jar 文档重复占用内存的目的。

修改catalina.bat
添加

JAVA_OPTS="-Djava.awt.headless=true -Dfile.encoding=UTF-8 
-server -Xms1536m -Xmx1536m
-XX:NewSize=256m -XX:MaxNewSize=256m -XX:PermSize=256m 
-XX:MaxPermSize=256m -XX:+DisableExplicitGC"1.2.3.4.

样例

#   JSSE_HOME       (Optional) May point at your Java Secure Sockets Extension
#                   (JSSE) installation, whose JAR files will be added to the
#                   system class path used to start Tomcat.
#
#   CATALINA_PID    (Optional) Path of the file which should contains the pid
#                   of catalina startup java process, when start (fork) is used
#
# $Id: catalina.sh 609438 2008-01-06 22:14:28Z markt $
# -----------------------------------------------------------------------------
 
JAVA_OPTS="-Djava.awt.headless=true -Dfile.encoding=UTF-8 -server -Xms1536m 
-Xmx1536m -XX:NewSize=256m -XX:MaxNewSize=256m -XX:PermSize=256m 
-XX:MaxPermSize=256m -XX:+DisableExplicitGC"
 
 
# OS specific support.  $var _must_ be set to either true or false.
cygwin=false
os400=false
darwin=false
case "`uname`" in
CYGWIN*) cygwin=true;;
OS400*) os400=true;;
Darwin*) darwin=true;;
esac
 
# resolve links - $0 may be a softlink
PRG="$0"1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.

具体参数根据自己机器情况而定

JAVA_OPTS="-Djava.awt.headless=true -Dfile.encoding=UTF-8 -server -Xms512m 
-Xmx512m -XX:NewSize=256m -XX:MaxNewSize=256m -XX:PermSize=256m 
-XX:MaxPermSize=256m -XX:+DisableExplicitGC"

2.3 风险代价最小的方法升级jdk版本

一劳永逸,以后也不会出这个错了
在这里插入图片描述

2.4 排查代码消耗内存较多的类

发现打印的日志特别大也是有问题的,然后使用System.out.println()打印日志,打印了过多的xml文件也会有问题
在这里插入图片描述

在这里插入图片描述
所以都说不好建议不要用,那么多日志框架,建议用slf4j

2.5 分析方向

PermGen space从表面上看就是内存益出,解决方法也一定是加大内存。说说为什么会内存益出:这一部分用于存放Class和Meta的信息,Class在被 Load的时候被放入PermGen space区域,它和和存放Instance的Heap区域不同,GC(Garbage Collection)不会在主程序运行期对PermGen space进行清理,所以如果你的APP会LOAD很多CLASS的话,就很可能出现PermGen space错误。这种错误常见在web服务器对JSP进行pre compile的时候。改正方法:-Xms256m -Xmx256m -XX:MaxNewSize=256m -XX:MaxPermSize=256m 2、在tomcat中redeploy时出现outofmemory的错误. 可以有以下几个方面的原因:
1.使用了proxool,因为proxool内部包含了一个老版本的cglib.
2.log4j,最好不用,只用common-logging
3.老版本的cglib,快点更新到最新版。
4.更新到最新的hibernate3.2 3、
5.内存中加载的数据量过于庞大,如一次从数据库取出过多数据;
6.集合类中有对对象的引用,使用完后未清空,使得JVM不能回收;
7.代码中存在死循环或循环产生过多重复的对象实体;
8.使用的第三方软件中的BUG;
9.启动参数内存值设定的过小.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

赵广陆

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值