某系统在运行几天之后,变得非常的慢,所有功能几乎不能用,偶尔会报OutOfMemory。
注:
root:/xxx/java/jdk1.5.0_15/bin # ./jps
18830 Jps
28360 Bootstrap
root:/xxx/java/jdk1.5.0_15/bin # ps -ef | grep java
root 28360 1 1 Oct25 ? 07:12:12 /xxx/java/java/bin/java -Djava.util.logging.config.file=/home/zxin10/tomcat/conf/logging.properties -Xms800m -Xmx800m -XX:PermSize=128m -XX:MaxPermSize=512m -Xdebug -Xrunjdwp:transport=dt_socket,address=8348,server=y,suspend=n -Djava.endorsed.dirs=/home/zxin10/tomcat/common/endorsed -classpath :/home/zxin10/tomcat/bin/bootstrap.jar:/home/zxin10/tomcat/bin/commons-logging-api.jar -Dorg.apache.jasper.compiler.Parser.STRICT_QUOTE_ESCAPING=false -Dcatalina.base=/home/zxin10/tomcat -Dcatalina.home=/home/zxin10/tomcat -Djava.io.tmpdir=/home/zxin10/tomcat/temp org.apache.catalina.startup.Bootstrap start
root 19028 16771 0 14:06 pts/0 00:00:00 grep java
root:/xxx/java/jdk1.5.0_15/bin # ./jstat -gcutil 28360 500 0
S0 S1 E O P YGC YGCT FGC FGCT GCT
4.46 0.00 58.34 79.17 72.21 4966 116.404 1146 2764.054 2880.458
4.46 0.00 58.87 79.17 72.21 4966 116.404 1146 2764.054 2880.458
4.46 0.00 58.87 79.17 72.21 4966 116.404 1146 2764.054 2880.458
4.46 0.00 58.87 79.17 72.21 4966 116.404 1146 2764.054 2880.458
4.46 0.00 66.27 79.17 72.21 4966 116.404 1147 2764.054 2880.458
4.46 0.00 66.27 79.17 72.21 4966 116.404 1147 2764.054 2880.458
4.46 0.00 66.27 79.17 72.21 4966 116.404 1147 2764.054 2880.458
4.46 0.00 66.27 79.17 72.21 4966 116.404 1147 2764.054 2880.458
4.46 0.00 66.27 79.17 72.21 4966 116.404 1147 2764.054 2880.458
4.46 0.00 66.27 79.17 72.21 4966 116.404 1147 2764.054 2880.458
0.00 0.00 5.00 79.98 72.22 4966 116.404 1148 2767.206 2883.610
0.00 0.00 5.00 79.98 72.22 4966 116.404 1148 2767.206 2883.610
0.00 0.00 5.00 79.98 72.22 4966 116.404 1148 2767.206 2883.610
jstat命令中:
28360 — tomcat的进程号
500 — 采样间隔,单位毫秒
0 — 采样次数,0表示一直进行采样
采样数据中:S0、S1、E共同组成Young区。
S0 — Heap上的 Survivor space 0 区已使用空间的百分比
S1 — Heap上的 Survivor space 1 区已使用空间的百分比
E — Heap上的 Eden space 区已使用空间的百分比
O — Heap上的 Old space 区已使用空间的百分比
P — Perm space 区已使用空间的百分比
YGC — 从应用程序启动到采样时发生 Young GC 的次数
YGCT– 从应用程序启动到采样时 Young GC 所用的时间(单位秒)
FGC — 从应用程序启动到采样时发生 Full GC 的次数
FGCT– 从应用程序启动到采样时 Full GC 所用的时间(单位秒)
GCT — 从应用程序启动到采样时用于垃圾回收的总时间(单位秒)
一次YGC,会对Young区(S0、S1、E)进行一次垃圾回收。
一次FGC,会对Young区、Old区进行垃圾回收。
但是,看到的采样数据中,进行了2次FGC(红色部分中的蓝色部分),但是Old区并没有被回收,大体说明:Old区的内存几乎不会被回收,存在泄露。
在系统慢时的内存数据heap.bin进行导出。./jmap -histo 980
可以简单的查看内存状况
该命令执行的时候,会导致jvm假死,所以现场环境谨慎使用。有时候这个命令不能执行成功,多执行几次。(不成功原因:jvm繁忙之类)root:/xxx/java/jdk1.5.0_15/bin # ./jmap -heap:format=b 28360
28360 — tomcat的进程号
成功之后在此目录下,会生成heap.bin。
将这个文件下载到windows的本机环境,使用JVMmat进行分析。
下图红色部分表明Logger对象异常多。
点击上图的按钮Leak Suspects,出现泄露的界面:
点击Details链接后,可以看到泄露的对象:
LoggerFactory.java中:
protected void addLogger(Logger logger)
{
if (null != logger)
{
synchronized (this.loggers)
{
this.loggers.add(logger);
}
for (Outputter o : this.outputters)
{
logger.addOutputter(o);
}
}
}
其中
把一个临时变量永久保存,就出现内存回收不了,内存泄露的问题。
共享协议:署名-非商业性使用-相同方式共享 3.0 Unported 许可协议
声明:未作说明,则本文为智昊的空间原创。转载务必注明出处。
注意:转载须保留全文,如需修改请 联系作者。
本文永久地址:http://zhihao.info/sd/programm-language/java/one-java-memory-leak-solution/