引入sleak异常,Warning: Device is not tracking resource allocation处理

来源:互联网 发布:linux history 记录数 编辑:程序博客网 时间:2024/06/05 21:01

背景:

sleak是官方提供的工具.可以用来监控SWT中需要释放的资源的占用情况.(这些资源包括:Font,Color,Corsor,Image,gc等);

如何引入sleak可以参考官网:http://www.eclipse.org/swt/tools.php  

引入sleak有两种:

1.通过使用Sleak.java类.然后在启动之初通过代码调用. 通过一个Dialog展示.  

  openSleak()是一个是否开启Sleak的开关

if (openSleak()) {Policy.DEBUG_SWT_GRAPHICS = true;Policy.DEBUG_SWT_DEBUG = true;}Display display = PlatformUI.createDisplay();if (openSleak()) {new Sleak().open();}

2.通过引入插件org.eclipse.swt.tools.jar  插件中自带包含sleak在内的view

问题处理:

如果你搜索上述问题,很有可能的答案是:http://stackoverflow.com/questions/2108430/sleak-swt-tool-device-is-not-tracking-resource-allocation 

或者是上述官网的那个链接. 而且这样确实可以解决大部分的这个问题.  如果你的问题就此解决了  恭喜你.  我就脸黑的多了 到此 错误依旧.

问题处理(续):

问题深入探究:

各种翻墙搜依然除了上述答案的重复  一无所获.  但幸运的是我用的Sleak.java文件引入的.  有代码可跟也算是有一丝希望.Debug看源码

Sleak.java源码:

void refreshDifference() {

DeviceData info = display.getDeviceData();if (!info.tracking) {MessageBox dialog = new MessageBox(shell, SWT.ICON_WARNING | SWT.OK);dialog.setText(shell.getText());dialog.setMessage("Warning: Device is not tracking resource allocation");dialog.open();}Object[] newObjects = info.objects;Error[] newErrors = info.errors;
我找到了熟悉的错误.     原因就是info.tracking==false.  

display的初始化:

<span style="color:#000000;">public void open() {display = Display.getCurrent();....}</span>

当然通过这段代码我们可以获得更多信息. 

  1. open()函数在Sleak初始化后马上被调用.通过DisplaygetCurrent()获取PlatformUI.createDisplay()创建的Display.
  2. 核心目的是获取display的DeviceData   info中的tracking是是否信息被跟踪的标识符. info.objects和info.errors就是我们想要跟踪的资源信息     我继续debug发现info.objects和errors都是空的       这也是合情合理,人家的跟踪标识符显示不用跟踪 自然信息也就不存了       可以设想如果info.tracking==true的话,  info就会提供给我们想要的东西

问题核心变成:如何设置info.tracking=true;

我通过修改代码试图让info变为true  但无果.  于是继续跟踪Display的创建过程.发现端倪

public static Display createDisplay() {// setup the application name used by SWT to lookup resources on some// platformsString applicationName = WorkbenchPlugin.getDefault().getAppName();if (applicationName != null) {Display.setAppName(applicationName);}// create the displayDisplay newDisplay = Display.getCurrent();if (newDisplay == null) {if (Policy.DEBUG_SWT_GRAPHICS || Policy.DEBUG_SWT_DEBUG) {DeviceData data = new DeviceData();if (Policy.DEBUG_SWT_GRAPHICS) {data.tracking = true;}if (Policy.DEBUG_SWT_DEBUG) {data.debug = true;}newDisplay = new Display(data);} else {newDisplay = new Display();}}// workaround for 1GEZ9UR and 1GF07HNnewDisplay.setWarnings(false);// Set the priority higher than normal so as to be higher// than the JobManager.Thread.currentThread().setPriority(Math.min(Thread.MAX_PRIORITY, Thread.NORM_PRIORITY + 1));initializeImages();return newDisplay;}
我们发现了   DeviceData中的数据tracking和debug的初始化.  

  1. 能走进这段逻辑的条件是:Display.getCurrent()==null.  
  2. Policy.DEBUG_SWT_GRAPHICS和DEBUG_SWT_DEBUG需要有一个为true 
    这个我们都很熟悉    其实 这就是最初两个解决问题的方法和代码引入Sleak时  所设置的boolean变量 
  3. DeviceData中的tracking,debug在创建后设置   并作为display的构造函数入参传入display  这也解释了为什么我后来无法修改tracking的值
  4. 我们也可以猜想,已经创建好的display 捣乱的Display肯定没有走类似的可以设置tracking=true的逻辑

问题更加明确:

由于Display.getCurrent()!=null  所以没有进入这段逻辑   Policy的值都没有被读取就跳过了   所以之前的解决方法无效.
有多余Display在调用当前逻辑之前被创建了.

正常的Sleak都是在项目启动时马上创建Sleak的.  所以绝大多数PlatformUI.createDisplay()都是创建当前项目的第一个display(PS:这个方法名也说明了这个问题) .但是如果在这之前就已经有Display创建了.并且用的默认参数创建了DeviceData,PlatformUI.createDisplay()返回了这个display  sleak就罢工了.   所以我小概率的赶上了后者.   Stack Overflow上也有一个和我一样的倒霉蛋.

问题最终解决:

我通过断点Display的构造函数抓到了这个提前创建的display. 是一个Font的数据成员声明:

private Font font = new Font(null, "微软雅黑", 12, SWT.NONE);
显然在font,corsor等要被Display监听的数据  在创建之初需要Display参数,如果没有他们的内部就会自己创建一个默认的.(没有给DeviceData.tracking设置的机会)

我的项目是个RCP程序     声明Font的类是  app主插件的activator类;引入sleak的地方  application扩展点的app.start().  自然前者要比后者先执行.

通过测试:注掉Font的声明  sleak就正常工作了.  

感想:

跟底层代码是很多思想的根本体现和真正了解实现本质的重要一环. 

(PS: 本博客上午已完成编辑 不料网页失效未能察觉  全部遗失;平心静气,重写之)




0 0
原创粉丝点击