Java内存泄漏原因、判定及解决方法

Java内存泄漏原因、判定及解决方法


1 关于内存泄露

2 SUN JDK提供 JDKPI和最新的JDKTI对内存泄露进行检测。

3 试用内存泄露检测工具

3.1 JProbe

3.2 HPROF

3.3 JRockit Mission Console

正文

1 关于内存泄露

java虚拟机可以自动回收没有被引用的对象。但有时应用程序会有一些对象被引用了但不被使用。这样的对象越来越多的,而虚拟机不能自动回收,就会导致java程序使用的堆越来越多,当超过堆的限制时就会抛出OutOfMemory的错误。

基本上如果抛出OutOfMemory有两种原因:1。内存泄露,2。应用程序本身就是需要这么多的内存。

在启动java的时候加入 -verbosegc(Jrockit是-verbose:memory或gc)参数。每次垃圾回收都会把回收信息打印到标准输出中。如果回收后的内存时候随时间不断增长。那么应用程序肯定是有内存泄露。

确定是内存泄露后,就需要找到是那些对象占用了内存。这需要是使用工具进行检测。

2 SUN JDK提供 JDKPI和最新的JDKTI对内存泄露进行检测。

JDKPI是sun jdk采用的一种可以检测堆大小情况的c语言的接口。但这个接口1.5中已经被废止。

取而代之的是JDKTI

3 试用内存泄露检测工具

目的:找到一个可以对在Linux上启动虚拟机,进行监控的工具。并且是在生产环境下

3.1 JProbe

JProbe是Quest公司提供的工具。具有GUI界面(java写的界面)。可以显示每个类型占堆的大小。

工具有几个缺点:

1、只有通过JProbe启动的虚拟机,JProbe才能对其的堆进行检测。这就要求,虚拟机要和JProbe安装在一台机器上。但很多内存泄露是在生产环境中发现的。生产环境中的很多都是Linux机器,程序员通过ssh控制。要使用图形工具配置比较费劲。修正:应该可以象JRockit那样在服务器开通一个端口,在本地监控。但我没有仔细研究,应该和JProfiler差不多。

2、并没有使用服务器的启动脚本。如果你在脚本里修改了classpath,加载了新的类,就无法对这个类进行测试了。也就是说,即时在测试环境中,无法做到与生产环境完全一致,那么测试结果也就没什么意义了。

3.2 HPROF

HPROF是sun内置的工具。启动虚拟机的时候,加入参数可以控制是否使用Hprof。Hprof可以列出堆中占用内存最多的对象。

启动方式:在启动虚拟机的时候偶加入参数-Xrunhprof:head=site

查看方式:thread dmup的时候会生成java.hprof.txt文件。里边记录了head的详细信息。

这个工具的缺点是:

加入hprof的参数后,java虚拟机的运行非常慢。

据说

要比正常慢20倍。无法应用在生产环境中。

3.3 JRockit Mission Console

这个工具只能监控bea的虚拟机JRockit的运行情况,使用的接口也不是sun jdk的jvmpi或jvmti了。

在JRockitMissionConsole1.4.2中是集成在JRockit中的(jrockit-R27.4.0-jdk1.4.2_15\bin\jrmc.exe)。

基本的使用方法:在启动JRockit虚拟机时开放监控端口,JRockit Mission Console可以在任何机器上运行,对开放了端口的虚拟机进行监控。并且基本没有额外的系统开销,与sun jdk完全兼容。这样就可以在生产环境中启动jdk,然后在程序员的机器中对Linux上的jdk的的运行情况进行监控。这正式我想要的。

因为我们的服务器使用的是1.4.2。所以,首先下载JRockit 1.4.2的最新版本。并且要最新的,因为JRockit版本号低于1.4.2.10的似乎不能使用JRockit Mission Console 中的Memory Leak Detector。

JRockit 1.4.2 无论是在window还是Linux安装都非常方便,按bea的文档做就可以。

然后重新配置一个weblogic的domain。配置的时候指定使用JRockit作为虚拟机。

修改startWeblogi.sh脚本加入-Xmanagement:port=7090参数,最好也把-Xverbose:memory加上,可以看到垃圾回收的情况。启动weblogic。

在本机启动JRockit Mission Console,建立对服务器的连接,启动Memory Leak Detector就可以对java的堆进行监视了。

Memory Leak Detector有4个视图:

1、趋势:这视图里列出了所有类型,占堆的百分比,对象数,最重要的是“增长(字节/秒)”,这个列高了。就有可能是内存泄露。

注意:这个视图在jdk进行垃圾回收后才传回信息,也就是说,如果没有进行垃圾回收就不会刷新。建议通过点垃圾回收按钮刷新界面。

否则,虽然可以自动刷新,但增长这个列一直是0,不进行自动计算。也许是一个bug吧。

2、类型:这个视图,通过在趋势中对感兴趣的类,右键->显示引用类型来进入。主要显示了选中类,与引用选中类的类。用箭头显示中间的关系。非常漂亮。

3、实例:这个视图显示的是类的实例。是在类型中对感兴趣的类型 右键->显示实例,或最大数组中右键->显示实例切换到这个视图的。显示一些实例之间的引用关系。

4、分配堆栈跟踪:这里可以看到指定类是在那个类中的第几行被实例化的。

注意:只有切换到这个视图,才对指定的类进行跟踪。如果切换过来后,这个类没有被实例化过,那么也看不到任何调用信息。

这是最有用的一个视图。类型和实例虽然很全,但由于类之间的关系复杂,有时,并不能找的找到需要的信息。

这个工具的缺点是:使用Memory Leak Detector,

需要到bea下载license。这个license分为2中。

一种是开发用的,这种在jdk启动1小时后,Memory Leak Detector就失效了。必须重新启动虚拟机才行。

另一种是企业级的,需要收费,没有时间限制。


相关文档
最新文档