使用 Eclipse Memory Analyzer 检测内存泄漏问题

本文是关于在开发 Talend RCP 过程中碰到一个内存溢出问题的解决方案。使用的检测软件为 Eclipse Memory Analyzer (http://www.eclipse.org/mat/ ) ,是一个开源免费的内存分析工具,目前为 eclipse 的孵化项目,也是一个 eclipse RCP.

Talend 一款开源的 ETL 软件,提供数据集成服务。基于 eclipse RCP EMF, GEF JET 等技术开发。

 

Talend 软件系统中,一个 designer editor 是一个 mulit page editor, 它的实例是 MultiPageTalendEditor ,其中包含两页,第一页是一个 gef Editor ,用来显示 GEF 图形;第二页是一个 JavaEditor, 用来显示生成的代码。如下两图所示:

 

使用 Eclipse Memory Analyzer 检测内存泄漏问题_第1张图片  

使用 Eclipse Memory Analyzer 检测内存泄漏问题_第2张图片

 

 

 

 

    经过其他工具的测试发现 JavaEditor 如果用在 mulit page editor 中,关闭后,起实例无法回收,造成内存泄漏,因为 Editor 是一个非常频繁使用的功能项,所以该问题非常严重。

 

 

要使用 Eclipse Memory Analyzer ,首先要生成 dump 文件。

eclipse 中配置 Preferences -> Java -> Installed JREs, 定义 Jdk1.6 来运行 Talend.

Talend 运行后,执行一下打开 editor 的操作,在将 editor 关闭,这样虚拟机中保存了相应的堆栈信息。其实也就是执行一下你认为会产生内存泄漏的操作。

 

运行 jdk1.6 bin 目录下的 jconsole.exe ,运行后如下图所示,选择连接到运行的 Talend

 

  使用 Eclipse Memory Analyzer 检测内存泄漏问题_第3张图片

 

 

 

选择 Mbean -> com.sun.management -> HotSpotDiagnos -> Operations -> dumpHeap

在参数 p0 中填写保存 dump 文件的路径,例如 f:/my.hprof, 文件的后缀名要为 hprof

点击 dumpHeap 按钮生成 dump 文件。

 

 使用 Eclipse Memory Analyzer 检测内存泄漏问题_第4张图片

 

 

 

打开 Eclipse Memory Analyzer, 在菜单 File 下,选择打开刚才生成的 dump 文件。如下图:

 

 使用 Eclipse Memory Analyzer 检测内存泄漏问题_第5张图片

 

 

 

 

在第一行的 filter 中填写需要检查的类名,这里我要检查的类为 TalendJavaEditor 。在如下图所示的上下文菜单中选择 List objects -> with incoming references, 查看保存了 TalendJavaEditor 实例的引用。

 

使用 Eclipse Memory Analyzer 检测内存泄漏问题_第6张图片  

 

 

 

 

在如下图所示的上下文菜单中选择 Path To GC Roots -> exclude weak/soft references, 过滤掉弱引用,因为在这里弱引用不是引起问题的关键。

 

使用 Eclipse Memory Analyzer 检测内存泄漏问题_第7张图片  

 

 

 

 

从下图中,可以看到 JavaInfomationProvider 中保存了 TalendJavaEditor 的引用。所以打开 JavaInfomationProvider 的代码,进行检查。从下图的分析中,大概可以看出这是一个注册了的监听器没有反注册的问题,这也是引起内存泄露的原因中最常见的。

 

 使用 Eclipse Memory Analyzer 检测内存泄漏问题_第8张图片

 

 

 

public JavaInformationProvider (IEditorPart editor ) {

 

       fEditor = editor;

 

       if ( fEditor != null ) {

 

           fPartListener = new EditorWatcher ();

           IWorkbenchWindow window = fEditor .getSite ().getWorkbenchWindow ();

           window.getPartService ().addPartListener ( fPartListener );

 

           update ();

       }

    }

 

JavaInformationProvider 的构造方法中,保存了 TalendJavaEditor 的实例,并且注册了监听器。

 

 

 

 

public void partClosed (IWorkbenchPart part ) {

           if (part == fEditor ) {

               fEditor .getSite ().getWorkbenchWindow ().getPartService ().removePartListener ( fPartListener );

              fPartListener = null ;

           }

       }

 

 

EditorWatcher 的方法 partClosed 中,当关闭一个 designer editor 的时候,传进来的 part MultiPageTalendEditor ,而不是 JavaInformationProvider 保存的 TalendJavaEditor ,所以该 listener 永远不可能被反注册掉, GC 也就不可能回收 TalendJavaEditor 。对于该软件系统来所,这是一个致命的内存溢出问题。

 

 

转自:http://blog.csdn.net/moneyice/article/details/2644503

你可能感兴趣的:(eclipse)