大龙的博客

常用链接

统计

最新评论

linux server下 如何解决java内存泄漏(基本自创,网上的能找到的基本上都有问题)

最近遇到个麻烦事, oc4j跑一天就到max heap size了。然后容器中有些servlet运行就不正常了(表现为有些业务能用有些则不能,而且系统表现的其慢无比),所以个人最开始估计是1.分配内存失败,因为有时会打出OutOfMemory2.很多socket超时,因为%70都在做gc(yc,fc). 为了找到并验证这个问题,就把jre换成了jrrt(据说效率会提高很多倍,最主要是容易找内存泄漏的问题),而客户端用jmc来进行线程堆栈和内存分析. 但首先遇到的问题就是: 由于是移动的项目,服务器在移动机访,对外网访问服务器有严格的控制,想要开一些端口,得走很长的开端口流程。目前oc4j几乎每天都会出问题,于是等不了那么久了。 因为我有服务器root权限,所有想绕过这个限制就很easy了。下面介始两种方法,让无论客户机是linux还是windows都可以把jmc用起来。

一、用tunnels技术

第一步:下载jrrt.

第二步: oc4j 启动参数设成: java -Xmx2000m -server -Djava.awt.headless=true -verbosegc -Dcom.sun.management.jmxremote.port=6666 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Djava.rmi.server.hostname=localhost -Dstdstream.filesize=100 -Dstdstream.filenumber=1000 -jar oc4j.jar -userThreads -out /opt/lbsonelog/oc4j.out -err /opt/lbsonelog/oc4j.err
记的要把$JRE_HOME改成jrrt的路径, 改好后启动。再运行jrcmd pid memleakserver 目得是监听tcp-7095 端口, 没有这个端口,是不能检查内存泄漏的。

第三步:如果是windows,那么下载putty(securecrt不行,不支持tunnels),如果是linux则用ssh就可以了。

第四步:1.putty配置tunnels的方法,  6666--->localhost:6666 netstat -tnpl查看随机端口, 然后 随机端口---->localhost:随机端口 (只有前面这两个端口能连上,才能在jmc中测试连接成功。切记) 7095-->localhost:7095 (用来检查内存泄漏的)  2.linux下的sshssh -L port:host:hostport -l login_name ip 比如:ssh -L 5901:localhost:5901 -l gate 211.x.x.x

第五步: 下载jmc

第六步:运行jmc, 新建连接中填 localhost, 6666. 测试连接,如果显示确定。 就表示成功了。

二、用vnc(前提是有一个开放的端口或先用上面的方法把这个端口做tunnel)
1
、想改端口的话,可以在/usr/bin/vncserver中先定义$default_port=9000;然后找到5900后用$default_port替换。然后监听的端口就成了,9000+N了。
2
、在/root/.vnc/xstartup中,把最后一行twm&vnc支持的不好)改成 gnome-session &
3
、如果让display固定在1, 那么可以删除 /tmp.X*-lock,和/tmp/.X11-unix下的所有文件。
4
、用vncviewer 直接连接服务器上的端口或者连接用tunnel做的localhost端口。
5
、装上linux下的jmc,在本地那里自动会出现oc4j.

通过上面的两种方法都可以跑起来。两种我都玩过了,都没什么问题。

最后用jmc分析后,发现占用内存最多的是[B, [C(就是byte[]char []),占了目前堆的80%以上,直接点右键进堆栈,发现来自oracle.jdbc上面,为什么呢?然后go oracle官网,通过一翻搜索,最终得到的结论是oc4j的数据库连接池配置不对,一看目前配置的是connection: mix:200-max:10000, stmt-cach-size:200, stmt cach的意思是为了提高效率,oracle.jdbc会自己存一份引用,所以在应用层就是close了,如果一个连接没超过200这个数,也是不会gc的,所以只要跑一段时间后,内存的占用就成了: 当前连接数(一般出问题时这个都超过1000 * 200 * 每条sql查出的数据的大小,如果一个语句查出的结果是5K, 那么这个内存占用可真不小了,1g呀,我的个妈呀,真是害人不浅呀。然后就把connection设成10-100stmt-cach-size:10。然后又看了下目前运行的线程,直觉告我不太正常,分析之,发现有个线程会把前面的connection的数量一下提搞到很高,而且线程sleep很短,结果会造成创建出的connection要远远快于gc回收的connection,经过一段时间后,就会出现最开始说的60%的时间用在了gc上,一gc就会把所有线程锁死,所以表现为有些业务不正常了。马上想了个好办法修改之。然后启动oc4j通过一晚上的奔跑,内存大部分时间都稳定在200m左右。成功解决此问题。

posted on 2011-10-16 05:58 大龙 阅读(1257) 评论(0)  编辑 收藏 引用


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理