码迷,mamicode.com
首页 > 其他好文 > 详细

Tomcat/JVM性能优化(也就PermGen排查啦)

时间:2015-07-08 16:48:00      阅读:196      评论:0      收藏:0      [点我收藏+]

标签:

最近一个SSH2项目升级了框架,部署后发现执行一段时间就会无法访问(Tomcat及其下其它Web可以正常访问)。

MyEclipse中进行“压力测试”时报错:Exception in thread "com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#0" java.lang.OutOfMemoryError: PermGen space

之后的现象跟测试机上部署的一样,初步判断就是这个原因。结合这个Exception,究其根本的原因,可能是框架第三方Jar包,class文件占有量变大;另一方面,有些模块请求历史数据时随着时间累积会返回较多的JSON数据,存放在Action的成员String变量中,通过Struts框架返回给前端,而前面说的这些,正好是存放在永久代(PermGen)里的。还有一个是测试部署的时候出现Exception loading sessions from persistent storage

java.io.WriteAbortedException: writing aborted; java.io.NotSerializableException: ... 当时的解决方法是相应的Bean继承Serializable接口,同时把work/Catalina/localhost/的项目文件夹给删了。总所周知,这个是jsp编译后的文件存放的目录,而PermGen OutOfMemoryError也容易发生在web服务器对JSP进行pre compile的时候。综上所述,那么就先看看PermGen的分配使用情况吧。

jstat内存监控(http://docs.oracle.com/javase/1.5.0/docs/tooldocs/share/jstat.html):

例如查看PermGen:jstat -gcpermcapacity pid

Windows上查看进程:tasklist | findstr javaw.exe

jstat内存监控出现pid not found:

在服务器上对部署的项目查看PermGen时,jstat出现pid not found的问题。jstat的基本原理是会生成一个hsperfdata_username的目录(里面存有pid文件,记录进程的信息),默认是在java.io.tmpdir目录下(linux上默认是/tmp下),但是我执行jstat的时候这个目录下没有pid文件。而网上资料说jdk1.6.0.23/24版本兼容性问题,而我正好使用了0.23,踩坑了。

While it‘s true that 6u23/24 introduce this issue, it‘s not a bug in jps. Rather a change in behavior of the VM itself. On GNU/Linux Jps and the likes seem to only look at /tmp but not necessarily your CATALINA_TMPDIR. If set or not, try to export CATALINA_TMPDIR=/tmp which translates to "-Djava.io.tmpdir=/tmp" and after restarting the Tomcat process you should see Tomcat‘s data as "/tmp/hsperfdata_/" and Jps will most likely work again as well.

解决办法是修改VM的配置文件,在tomcat/bin/catalina.sh中,找到CATALINA_TMPDIR,改为CATALINA_TMPDIR=/tmp,在重启tomcat就可以了。

继续在本地进行“压力测试”,结果出现问题时,PermGen的PGC/PC已被消耗光,YGC/FGC次数不断攀升,同时FGCT/GCT也持续增加,很明显,JVM尝试不断进行GC试图释放PermGen,但是似乎力不从心,导致程序一直被阻塞。那么,改PermGen参数咯。

更改Tomcat的JVM PermGen参数:

因为是本地MyEclipse以debug方式启动tomcat的,在按照网上所说的方法在%CATALINA_HOME%/bin/catalina.bat中Execute The Requested Command后增加set JAVA_OPTS=%JAVA_OPTS%-server -XX:PermSize=128m -XX:MaxPermSize=256m后,debug启动无效,其实这个时候tomcat是被调用tomcat7.exe启动,所以无法使得catalina.bat中的参数生效。

正确的方式是在MyEclipse -> Preferences -> Servers -> Tomcat -> Tomcat x.x -> JDK的Optional Java VM arguments中增加

-XX:PermSize=128M

-XX:MaxPermSize=256M

再启动即可。

本来PermSize设置为64M,Web项目启动执行过程中,如果不够用时它会按照某种方式增量分配,比如FGC一下,PGC/PC增到140M,接下来还会适时地FGC,又减到135M、130M之类。这样多累啊,不如初始分配时多一点,分配128M咯,然后再测试,执行时观察过程中并没有发生FGC。

就这样?其实我也想从代码上进行优化,以提高内存利用率,排除可能存在的内存泄露之类的问题。但是老代码太多(问题是升级过程中,大部分代码并未动过,只是新增了部分小模块),很怀疑是SSH框架(Spring3.2.1、Struts2.3.4、Hibernate3.3.2)的问题。这方面,大家有经验的请多指教。平常关注业务,都没时间去挖掘技术细节了。。。


Tomcat/JVM性能优化(也就PermGen排查啦)

标签:

原文地址:http://my.oschina.net/iuranus/blog/476133

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!