应用场景:在打开的编辑器中创建类图,每打开一次都要用到类图、字体、颜色资源。
分析原因:
1.在eclipse中图片、字体、颜色都属于org.eclipse.swt.graphics.Resource资源。
public final class Image extends Resource implements Drawable{...}
public final class Font extends Resource{....}
public final class Color extends Resource {...}
而该类型明确说明
* Application code must explicitly invoke the <code>Color.dispose()</code>
* method to release the operating system resources managed by each instance
* when those instances are no longer required.
意思就是说当这些资源实例不在使用的时候,必须调用dispose释放掉。即遵循了谁创建谁负责的原则。
Java开发人员在使用SWT/JFACE的时候,并不能借助于Java内置的垃圾回收机制来彻底完成系统资源的清理(Java虚拟机只能帮助我们释放虚拟机内存中的系统资源句柄引用对象)。
所以当我们在程序中大量的创建资源实例,就会引起大量句柄,导致资源句柄不够用,引发no more handles异常。所以不允许每次都new image/create image或其他资源。
解决办法:
JFaceResources是JFace中的资源管理门面类,由它获取我们的图片、字体、颜色并进行缓存,相应的处理方法如下
JFaceResources.getImageRegistry();
JFaceResources.getFontRegistry();
JFaceResources.getColorRegistry();
以上三个方法都使用了map对资源进行了缓存,所以你只需要put一次,在其他地方get就
ok了。
比如:
/*** [email protected] [email protected]*/
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错误。