现在的位置: 首页 > 综合 > 正文

JAVA内存泄漏分析(四)

2012年05月13日 ⁄ 综合 ⁄ 共 1822字 ⁄ 字号 评论关闭
怎么解决Java内存泄漏<二>
文章出处:http://hi.baidu.com/robin300/blog/item/472aeccd6295c7510fb34588.html
内存泄漏探测工具

  有很多专门的内存泄漏探测工具。其中The JRockit Memory Leak Detector可以供来观察内存泄漏也可以针对性地找到泄漏的原因。这个强大的工具被紧密地集成在JRockit JVM中,可以提供最低可能的内存事务也可以轻松的访问虚拟机的堆。

  专门工具的优势

  一旦你知道程序中存在内存泄漏,你需要更专业的工具来查明为什么这里会有泄漏。而JVM是不可能告诉你的。现在有很多工具可以利用了。这些工具本质上主要通过两种方法来得到JVM的存储系统信息的:JVMTI和字节码使用仪器。Java虚拟机工具接口(JVMTI)和他的原有形式JVMPI(压型接口)都是标准接口,作为外部工具同JVM进行通信,搜集JVM的信息。字节码使用仪器则是引用通过探针获得工具所需的字节信息的预处理技术。

  通过这些技术来侦测内存泄漏存在两个缺点,而这使得他们在产品级环境中的运用不够理想。首先,根据两者对内存的使用量和内存事务性能的降级是不可以忽略的。从JVM 获得的堆的使用量信息需要在工具中导出,收集和处理。这意味着要分配内存。按照JVM的性能导出信息是需要开销的,垃圾回收器在搜集信息的时候是运行的非常缓慢的。另一个缺点就是,这些工具所需要的信息是关系到JVM的。让工具在JVM开始运行的时候和它关联,而在分析的时候,分离工具而保持JVM运行,这显然是不可能的。

  既然JRockit Memory Leak Detector是被集成到JVM中的,那么以上两种缺点就不再适用。首先,大部分的处理和分析都是在JVM中完成的,所以就不再需要传送或重建任何数据。处理也可以在垃圾回收器的背上,他的意思是提高速度。再有,内存泄漏侦测器可以同一个运行的JVM关联和分离,只要JVM在开始的时候伴随着 -Xmanagement选项(这个允许监听和管理JVM通过远程JMX接口)。当工具分离以后,工具不会遗留任何东西在JVM中;JVM就可以全速运行代码就好像工具关联之前一样。

  趋势分析

  让我们更深一步来观察这个工具,了解他如何捕捉到内存泄漏。在你了解到代码中存在内存泄漏,第一步就是尝试计算出什么数据在泄漏--哪个对象类导致泄露。The JRockit Memory Leak Detector通过在垃圾回收的时候,计算每个类所包含的现有的对象来达到目的。如果某一个类的对象成员数目随着时间增长(增长率),那么这里很可能存在泄漏。


Figure 2. The trend analysis view of the Memory Leak Detector

  因为一个泄漏很可能只是像水滴一样小,所以趋势分析必须运行足够长的一段时间。在每个短暂的时间段里,局部类的增加会使得泄漏发生推迟。但是,内存事务是非常小的(最大的内存事务是由在每个垃圾回收时从JRockit向内存泄漏探测器发送的一个数据包组成的)。内存事务不应该成为任何系统的问题--甚至一个在产品阶段全速运行的程序。

  一开始,数字会有很大的跳转,随时间的推进,这些数字会变得稳定,而后显示哪些类会不断的增大。

  寻找根本原因

  知道那些对象的类会导致泄露,有时候足够制止泄露问题。这个类也许只是被用在非常有限的部分,通过快速的视察就可以找到问题所在。不幸的是,这些信息是不够的。比方说,经常导致内存泄漏的对象类java.lang.String,然而String类被应用于整个程序,这就变得有些无助。

  我们想知道的是其他的对象是否会导致内存泄漏,好比上面提到的String类,为什么这些导致泄漏的对象还是存在周围?那些引用是指向这些对象的?这里一列的对象存有对String类的引用,就会变得太大而没有实际意义。为了限制数据的数量,我们可以通过类把他们编成一个组,这样我们就可以看到,那些其他类的对象会依然泄漏对象(String类)。比如,将一个String类放入Hashtable,那里我们可以看到关联到String类的 Hashtable入口。从Hashtable入口向后运行,我们终于找到那些关联到String类的Hashtable对象(参看图三如下)。


Figure 3. Sample view of the type graph as seen in the tool

抱歉!评论已关闭.