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错误。
相关推荐
在Android开发环境中,它作为Eclipse插件,能为开发者提供一个更高效、便捷的方式来查找和修复代码中的bug,特别是那些可能导致应用崩溃的问题。对于Linux用户而言,FindBugs 3.0版本提供了更加稳定和优化的体验。 ...
- [Developing Eclipse plug-ins](#):插件开发指南。 - [Plug a Swing-based development tool into Eclipse](#):如何将基于Swing的工具集成到Eclipse中。 #### 关于作者 Adrian Van Emmenis是一位独立顾问,...
这个压缩包通常包含了一些特定的插件和本地化资源文件,例如在提供的"eclipse_plugins"文件列表中,很可能包含了这些必要的组件。 安装步骤如下: 1. 解压下载的"eclipse_plugins"压缩文件到一个临时目录。 2. ...
在开发过程中,使用Eclipse作为集成开发环境(IDE)时,有时会遇到运行大型项目时出现内存溢出(OutOfMemoryError)的问题。这种情况不仅影响了开发效率,还可能打断开发流程。本文将详细介绍如何有效地解决Eclipse...
Eclipse插件FindBugs就是这样一个强大的静态代码分析工具,它能够帮助开发者在编译期间发现潜在的问题,从而提高代码质量。 **FindBugs简介** FindBugs是由University of Maryland开发的一款开源工具,它可以分析...
文件删除-递归访问文件系统-eclipse插件.zip"涵盖了Hadoop生态系统中的重要概念,特别是文件系统的操作,如文件删除和递归访问,以及如何利用Eclipse开发环境进行Hadoop相关的开发工作。 1. **Hadoop文件系统(HDFS...
这款插件使得Java开发者能够在Eclipse集成开发环境中直接创建、编辑和运行Hadoop MapReduce项目,极大地提高了开发效率。 Hadoop,由Apache基金会开发,是一个开源分布式计算框架,主要设计用于处理和存储海量数据...
Java和Eclipse是软件开发领域中的重要工具,尤其在Java应用程序开发中,Eclipse作为一款强大的集成开发环境(IDE)被广泛使用。本教程旨在帮助初学者和有经验的开发者更好地理解和掌握Java编程语言以及Eclipse IDE的...
Eclipse的SVN插件是开发人员在使用Eclipse集成开发环境时,进行版本控制的重要工具,特别是对于团队协作的项目来说,它使得代码管理变得高效且有序。本指南将详细介绍如何安装和使用Eclipse的SVN插件,并提供一些...
插件安装方式有两种:一种是在线安装,直接在Eclipse中搜索并安装;另一种是离线安装,先下载插件包,然后通过`Help -> Install New Software`导入。 #### 五、设置字体 - **Windows 7环境下**: 1. 在**控制面板...
总的来说,JFormDesigner-5.1.1-eclipse插件是Java UI设计领域的一款利器,它的出现极大地提高了开发效率,降低了设计复杂度。通过深入理解和熟练运用这款插件,开发者可以打造出更加专业、高效的用户界面,提升软件...
例如,文中提到的“org.eclipse.jdt.core_3.6.1.v_A68_R36x.jar”文件,将其解压后替换掉Eclipse插件目录下的同名文件。 2. 确保新版本的插件与你的Eclipse版本相兼容,避免引入新的问题。 #### 步骤三:优化系统...
7. **资源管理**:游戏中的图片、声音等资源需要被正确加载和释放,防止内存泄漏。Java提供了诸如InputStream和BufferedImage等类来处理资源。 通过Eclipse飞机大战这款游戏,开发者不仅可以提升自己的Java编程技能...
**SWT在Eclipse插件开发中的应用:** Eclipse插件通常使用SWT和JFace结合的方式进行开发,这样既可以利用SWT的高性能和原生外观,又能享受到JFace提供的高级功能。例如,可以通过SWT创建窗口、菜单和按钮,然后使用...
为了配置Eclipse进行J2ME开发,你需要安装相应的插件,如EclipseME或Wireless Toolkit(WTK),这些工具集成了模拟器,使开发者能在实际设备之前测试和调试应用程序。 在讲座中,可能会讲解以下关键知识点: 1. **...
- **清理metadata**:Eclipse的工作空间中包含了大量的元数据,定期清理`.metadata\.log`文件和 `.lock`文件可以释放空间。 - **禁用自动构建**:在`Window > Preferences > General > Workspace`中,取消选中...
- 安装Eclipse CDT(C/C++ Development Tooling)插件,这是Eclipse用于C/C++开发的核心组件。 - 配置Linux交叉编译工具链,以便在非Linux系统上编译Linux驱动。 - 准备Linux内核源码,确保可以访问到相关的...
2. **异常处理**:手册中对异常处理有明确的规定,提倡精确抛出和捕获异常,避免使用空异常类,以及在finally块中释放资源。此外,还鼓励使用自定义异常来增强代码的可读性。 3. **设计模式**:手册推荐使用常见的...
- 卸载插件相对简单,只需在Eclipse的`plugins`目录或者`features`目录中删除对应的插件文件即可。 #### 五、项目管理和构建 1. **构建自动化** - Eclipse支持构建自动化,可以在项目的属性设置中选择是否开启。...
在"eclipse-rcp-indigo-SR2-win32-x86_64"压缩包中,"eclipse"文件夹包含了运行Eclipse RCP应用所需的全部资源,包括JRE(Java Runtime Environment)、Eclipse插件、工作台配置、启动脚本等。用户可以通过运行...