本文是关于在开发 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, 用来显示生成的代码。如下两图所示:
经过其他工具的测试发现 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 。
选择 Mbean -> com.sun.management -> HotSpotDiagnos -> Operations -> dumpHeap
在参数 p0 中填写保存 dump 文件的路径,例如 f:/my.hprof, 文件的后缀名要为 hprof 。
点击 dumpHeap 按钮生成 dump 文件。
打开 Eclipse Memory Analyzer, 在菜单 File 下,选择打开刚才生成的 dump 文件。如下图:
在第一行的 filter 中填写需要检查的类名,这里我要检查的类为 TalendJavaEditor 。在如下图所示的上下文菜单中选择 List objects -> with incoming references, 查看保存了 TalendJavaEditor 实例的引用。
在如下图所示的上下文菜单中选择 Path To GC Roots -> exclude weak/soft references, 过滤掉弱引用,因为在这里弱引用不是引起问题的关键。
从下图中,可以看到 JavaInfomationProvider 中保存了 TalendJavaEditor 的引用。所以打开 JavaInfomationProvider 的代码,进行检查。从下图的分析中,大概可以看出这是一个注册了的监听器没有反注册的问题,这也是引起内存泄露的原因中最常见的。
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