学习前先看下内存溢出的分类: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.启动参数内存值设定的过小.