1.问题提出
在插件开发代码中,大量使用了图片作为图标,在相应的view,editor中展示,初始时测试还OK,但是经过长时间的使用后,经常报出SWT:No More Handlers的错误,异常如下所示:
!ENTRY org.eclipse.osgi 4 0 2013-07-30 15:49:55.671 !MESSAGE Application error !STACK 1 org.eclipse.swt.SWTError: No more handles at org.eclipse.swt.SWT.error(SWT.java:3803) at org.eclipse.swt.graphics.Image.init(Image.java:1582) at org.eclipse.swt.graphics.Image.<init>(Image.java:177) at org.eclipse.swt.widgets.Composite.WM_PAINT(Composite.java:1367) at org.eclipse.swt.widgets.Control.windowProc(Control.java:3842) at org.eclipse.swt.widgets.Canvas.windowProc(Canvas.java:337) at org.eclipse.swt.widgets.Display.windowProc(Display.java:4541) at org.eclipse.swt.internal.win32.OS.UpdateWindow(Native Method) at org.eclipse.swt.widgets.Decorations.setVisible(Decorations.java:1389) at org.eclipse.swt.widgets.Shell.setVisible(Shell.java:1764) at org.eclipse.swt.widgets.Shell.open(Shell.java:1150) at org.eclipse.jface.window.Window.open(Window.java:797) at org.eclipse.ui.internal.WorkbenchWindow.open(WorkbenchWindow.java:778) at org.eclipse.ui.internal.Workbench$61.runWithException(Workbench.java:3402) at org.eclipse.ui.internal.StartupThreading$StartupRunnable.run(StartupThreading.java:31) at org.eclipse.swt.widgets.RunnableLock.run(RunnableLock.java:35) at org.eclipse.swt.widgets.Synchronizer.runAsyncMessages(Synchronizer.java:133) at org.eclipse.swt.widgets.Display.runAsyncMessages(Display.java:3800) at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3425) at org.eclipse.ui.application.WorkbenchAdvisor.openWindows(WorkbenchAdvisor.java:803) at org.eclipse.ui.internal.Workbench$27.runWithException(Workbench.java:1363) at org.eclipse.ui.internal.StartupThreading$StartupRunnable.run(StartupThreading.java:31) at org.eclipse.swt.widgets.RunnableLock.run(RunnableLock.java:35) at org.eclipse.swt.widgets.Synchronizer.runAsyncMessages(Synchronizer.java:133) at org.eclipse.swt.widgets.Display.runAsyncMessages(Display.java:3800) at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3425) at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:2295) at org.eclipse.ui.internal.Workbench.access$4(Workbench.java:2200) at org.eclipse.ui.internal.Workbench$5.run(Workbench.java:495) at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:288) at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:490) at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:149) at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:113) at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:193) at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110) at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79) at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:386) at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:179) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:549) at org.eclipse.equinox.launcher.Main.basicRun(Main.java:504) at org.eclipse.equinox.launcher.Main.run(Main.java:1236) ……
经过排查以及从网上学习了解到,SWT/JFace中的图片资源是需要自己管理释放的。
2.问题分析
Java开发人员在使用SWT/JFACE的时候,并不能借助于Java内置的垃圾回收机制来彻底完成系统资源的清理(Java虚拟机只能帮助我们释放虚拟机内存中的系统资源句柄引用对象)。在SWT中系统资源对象的定级类型是org.eclipse.swt.graphics.Resource,在类型明确说明了“Resources created by the application must be disposed”
在eclipse插件开发的时候,很多地方都需要用到图片之类的资源,而在SWT中图片资源是需要手动释放的。手动释放时机却很难把握,尤其是图片可能被多个地方用到的时候。可以参考:http://southking.iteye.com/blog/316449对资源的解释,下面就说一下如何经过代码改动来避免资源释放问题。
下面列出几个比较容易出现句柄(本例子中是Image图片资源)数量超出的地方代码:
构造函数直接创建
new Image(Device device, InputStream stream)
通过ImageDescriptor+Path直接创建Image
private Image getImage(String path){ ImageDescriptor desc = AbstractUIPlugin.imageDescriptorFromPlugin(ID, path); return desc.createImage(); }
通过ImageDescriptor+URL直接创建Image
private Image getImage(String path){ URL url = null; try{ url = new URL(Activator.getDefault().getDescriptor().getInstallURL(), path); }catch(MalformedURLException e){ e.printStackTrace(); } ImageDescriptor imageDescriptor = ImageDescriptor.createFromURL(url); return imageDescriptor.createImage(); }
3.问题处理
JFaceResources是JFace中的资源管理门面类,由它获取我们的图片资源并进行缓存,相应的处理方法如下,写在对应bundle的Activator中,使用JFacesResources来对ImageDescriptor中的Image进行缓存操作。
/** * 懒加载的方式添加Image资源的处理 * @param imageFilePath * @return */ public static Image imageFromPlugin(String imageFilePath) { Image image = JFaceResources.getImageRegistry().get(imageFilePath); if(image != null) { return image; } else { ImageDescriptor imageDescriptorFromPlugin = imageDescriptorFromPlugin(PLUGIN_ID(本插件的ID), imageFilePath); image = imageDescriptorFromPlugin.createImage(); JFaceResources.getImageRegistry().put(imageFilePath, image); return image; } }
使用这种方式时,注意一点,Activator中的stop方法手动将资源管理器中的资源释放掉:
public void stop(BundleContext bundleContext) throws Exception { JFaceResources.getImageRegistry().dispose(); Activator.context = null; plugin = null; }
此后在使用图片资源时,都使用了这种方式,通过Activator. imageFromPlugin(imageFilePath)获取Image对象。
当然有些接口中要求返回的是ImageDescriptor,直接调用
ImageDescriptor org.eclipse.ui.plugin.AbstractUIPlugin.imageDescriptorFromPlugin(String pluginId, String imageFilePath)
方法即可,不会造成No more handlers错误。
相关推荐
eclipse插件开发指南.pdfeclipse插件开发指南.pdf
Eclipse插件开发学习笔记.pdf Eclipse插件开发学习笔记.pdf Eclipse插件开发学习笔记.pdf
Eclipse插件开发教程PPT Eclipse插件开发教程PPT
Eclipse插件开发中编辑器代码的定位、背景色改变、高亮
Eclipse插件开发方法与实战,一本不错的eclipse的插件开发参考书,感兴趣的可以下下看看!
《Eclipse插件开发》由浅入深、有重点、有针对性地介绍了Eclipse插件开发技术,全书分为4篇共24章。第一篇介绍Eclipse平台界面开发的基础知识,包括SWT控件的使用、界面布局、事件处理等内容;第二篇是插件开发核心...
资源名称:Eclipse插件开发学习笔记内容简介:《Eclipse插件开发》由浅入深、有重点、有针对性地介绍了Eclipse插件开发技术,全书分为4篇共24章。第一篇介绍Eclipse平台界面开发的基础知识,包括SWT控件的使用、界面...
Eclipse插件开发指南 Eclipse插件开发指南
《Eclipse插件开发(原书第3版)(畅销插件开发指南新版)》主要介绍了开发Eclipse商业插件的完整过程,并从标准窗口小部件工具集、命令与操作、视图、透视图、实现帮助、国际化等方面对创建Eclipse商业插件进行了详细...
Eclipse插件开发Eclipse插件开发Eclipse插件开发Eclipse插件开发http://www.ibm.com/developerworks/cn/java/os-ecplug/
本书第一篇介绍Eclipse平台界面开发的基础知识,包括SWT控件的使用、界面布局、事件处理等...本书内容全面,讲解仔细,不仅适合没有Eclipse平台技术基础的相关人士,也适合了解相关技术、具有一定插件开发能力的读者。
《Eclipse插件开发学习笔记》PDF 高清版
本书由浅入深、有重点、有针对性地介绍了Eclipse插件开发技术,全书分为4篇共24章。第一篇介绍Eclipse平台界面开发的基础知识,包括SWT控件的使用、界面布局、事件处理等内容;第二篇是插件开发核心技术,主要介绍...
《Eclipse插件开发》是一本介绍Eclipse插件开发的权威参考书。它对Eclipse插件开发进行了全程详细指导,内容不仅包括Eclipse使用入门、Eclipse基础结构、SWT、JFace、操作、视图、透视图、标记、性质、构建器等插件...
eclipse插件开发指南.pdf eclipse插件开发指南.pdf eclipse插件开发指南.pdf
Eclipse插件开发指南-陈刚Eclipse插件开发指南-陈刚Eclipse插件开发指南-陈刚Eclipse插件开发指南-陈刚Eclipse插件开发指南-陈刚Eclipse插件开发指南-陈刚
《Eclipse插件开发(原书第3版)(畅销插件开发指南新版)》主要介绍了开发Eclipse商业插件的完整过程,并从标准窗口小部件工具集、命令与操作、视图、透视图、实现帮助、国际化等方面对创建Eclipse商业插件进行了详细...
Eclipse插件开发问题,欢迎探讨与学习。
Eclipse插件开发教程 Eclipse插件开发
Eclipse插件开发系列