tomcat的reloadable特性引发的PermGen space

这两天遇到Tomcat  报java.lang.OutOfMemoryError: PermGen space 的问题,解决办法分享给大家!

  1. PermGen space 是什么

PermGen space的全称是Permanent Generation space,是指内存的永久保存区域。

SUN JVM分代垃圾回收器把堆空间分成3块:

  • Young Gen:年轻代,包括1个Eden区和2个Suvivor区,新创建的对象(大部分为短周期的对象)将进入这个区,虚拟机会频繁地对这个区进行垃圾回收。
  • Old Gen:年老代,当对象在Young Gen呆地足够久(经过几次的垃圾回收仍然存在)或Young Gen空间不足时,对象将进入Old Gen,由于一般是生命周期比较长的对象,因此虚拟机对这块内存的回收频度会比较低,一旦回收,使用的将是一个耗时的Full GC,另外,一旦堆空间不足时,虚拟机也会尝试去回收这个区。
  • Perm Gen:持久代,一些常量定义和类、方法声明及其bytecode都会放在这个区

 

 2.通常什么情况下出现PermGen space 

OutOfMemoryError: PermGen space从表面上看就是内存益出。说说为什么会内存益出:这一部分用于存放Class和Meta的信息,Class在被 Load的时候被放入PermGen space区域,它和和存放Instance的Heap区域不同,GC(Garbage Collection)不会在主程序运行期对PermGen space进行清理,所以如果你的APP会LOAD很多CLASS的话,就很可能出现PermGen space错误。

 

 3. visualvm、jstat  分析jvm工具

     jvisualvm

     jvisualvm:监控内存泄露,跟踪垃圾回收,执行时内存、cpu分析,线程分析...

    在JDK_HOME/bin目录下面,有一个jvisualvm.exe文件,双击打开

160643_zzV4_2418341.png

 

  监控项总共分为概述,监视,线程和一个抽样。

160702_0z3x_2418341.png

 

  • 概述包括 jvm启动参数,系统参数)

160710_Jgfj_2418341.png

如果选择Eclipse还可以可以看到eclipase 的启动参数;

  • 监视

160719_e81o_2418341.png

左上:cpu利用率,gc状态的监控

右上:堆利用率,永久内存区的利用率

左下:类的监控

右下:线程的监控

performGC:gc的详细运行状态

HeapDump:堆的详细状态(可以看到堆的概况,里面所有的类,还能点进具体的一个类查看这个类的状态)

 

  • 线程

160735_QPsG_2418341.png

能够显示线程的名称和运行的状态,在调试多线程时必不可少,而且可以点进一个线程查看这个线程的详细运行情况

参考:http://blog.csdn.net/a19881029/article/details/8432368

          http://www.ibm.com/developerworks/cn/java/j-lo-visualvm/

 

Jstat

 

Jstat 是JDK自带的一个轻量级小工具。全称“Java Virtual Machine statistics monitoring tool”,它位于java的bin目录下,主要利用JVM内建的指令对Java应用程序的资源和性能进行实时的命令行的监控,包括了对Heap size和垃圾回收状况的监控。可见,Jstat是轻量级的、专门针对JVM的工具,非常适用。

160743_ZDld_2418341.png

可以列出当前JVM版本支持的选项,常见的有

  • l  class (类加载器) 
  • l  compiler (JIT) 
  • l  gc (GC堆状态) 
  • l  gccapacity (各区大小) 
  • l  gccause (最近一次GC统计和原因) 
  • l  gcnew (新区统计)
  • l  gcnewcapacity (新区大小)
  • l  gcold (老区统计)
  • l  gcoldcapacity (老区大小)
  • l  gcpermcapacity (永久区大小)
  • l  gcutil (GC统计汇总)
  • l  printcompilation (HotSpot编译统计)

 

参考:http://docs.oracle.com/javase/1.5.0/docs/tooldocs/share/jstat.html#class_option

          http://nassir.iteye.com/blog/1517484

 

 

4.解决内存溢出的问题

1.手动设置MaxPermSize的大小, TOMCAT_HOME/bin/catalina.bat(Linux上为catalina.sh)文件

set JAVA_OPTS=%JAVA_OPTS% %LOGGING_CONFIG% -Xms256m -Xmx512m -XX:MaxNewSize=256m -XX:MaxPermSize=256m

常见配置汇总 
堆设置 
-Xms:初始堆大小 
-Xmx:最大堆大小 
-XX:NewSize=n:设置年轻代大小 
-XX:NewRatio=n:设置年轻代和年老代的比值.如:为3,表示年轻代与年老代比值为1:3,年轻代占整个年轻代年老代和的1/4 
-XX:SurvivorRatio=n:年轻代中Eden区与两个Survivor区的比值.注意Survivor区有两个.如:3,表示Eden:Survivor=3:2,一个Survivor区占整个年轻代的1/5 
-XX:MaxPermSize=n:设置持久代大小
收集器设置 
-XX:+UseSerialGC:设置串行收集器 
-XX:+UseParallelGC:设置并行收集器 
-XX:+UseParalledlOldGC:设置并行年老代收集器 
-XX:+UseConcMarkSweepGC:设置并发收集器
垃圾回收统计信息 
-XX:+PrintGC 
-XX:+PrintGCDetails 
-XX:+PrintGCTimeStamps 
-Xloggc:filename
并行收集器设置 
-XX:ParallelGCThreads=n:设置并行收集器收集时使用的CPU数.并行收集线程数. 
-XX:MaxGCPauseMillis=n:设置并行收集最大暂停时间 
-XX:GCTimeRatio=n:设置垃圾回收时间占程序运行时间的百分比.公式为1/(1+n)
并发收集器设置 
-XX:+CMSIncrementalMode:设置为增量模式.适用于单CPU情况. 

-XX:ParallelGCThreads=n:设置并发收集器年轻代收集方式为并行收集时,使用的CPU数.并行收集线程数.

2.检查代码(不多说了)

3.Tomcat便于开发者开发,tomcat支持 热加载,但是当热加载次数变多也会造成内存溢出(也是本宝宝此次遇到的问题!~~~~(>_<)~~~~)

    原因是由于运行项目的classes目录文件变更引起tomcat reload,同时reload时没有释放资源引起的宕机。

  当您重新部署您的应用程序时,Tomcat 将创建新的类加载器。旧类加载器必须是垃圾回收 ,但是tomcat 每次热加载GC(Garbage Collection)不会在主程序运行期对 PermGen space进行清理 ,导致每次都又重新    加载一次所有的    class,最后加载的多了,就出现了PermGen space;

现象:用VisualVM时候,PermGen已经满了达到最大值了,类区的装入类总数达到了应用正常类的好多倍!最后程序直接挂掉!

 

 这种情况下无论你MaxPermSize改变的多大都不管用的,解决办法修改tomcat 的server.xml文件,让项目变更时不reload。160848_neyJ_2418341.png

reloadable 改成 false; 就这么简单! tomcat 的坑啊!

 

  1. 这是应该用的不多吧,网上看到的,并且试了试  是好用的,只是程序响应比较慢,解决的不是本质的问题,但是还是有必要知道下,原理我并不懂,衰!

160806_Aph1_2418341.png

   参考地址:http://www.tuicool.com/articles/6BJJzin

5.tomcat 的 classload 机制

   网上文章比较多,不写了!哈哈,好懒!

 

最后看到JVM8 已经没有PermGen 了!参考:Java PermGen 去哪里了?

参考地址:http://ifeve.com/java-permgen-removed/

参考书籍:

1、分布式java应用基础

2、深入理解JVM

转载于:https://my.oschina.net/u/2418341/blog/672890

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值