JFace FontRegistry上的NoClassDefFoundError [英] NoClassDefFoundError on JFace FontRegistry

查看:149
本文介绍了JFace FontRegistry上的NoClassDefFoundError的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我启动SWT应用程序(通过Eclipse启动配置文件)时,我收到以下堆栈跟踪:

When I launch an SWT application (via an Eclipse launch profile), I receive the following stack trace:

Exception in thread "main" java.lang.NoClassDefFoundError: org/eclipse/jface/resource/FontRegistry
    at org.eclipse.jface.resource.JFaceResources.getFontRegistry(JFaceResources.java:338)
    at org.eclipse.jface.window.Window.close(Window.java:313)
    at org.eclipse.jface.dialogs.Dialog.close(Dialog.java:971)
    at org.eclipse.jface.dialogs.ProgressMonitorDialog.close(ProgressMonitorDialog.java:348)
    at org.eclipse.jface.dialogs.ProgressMonitorDialog.finishedRun(ProgressMonitorDialog.java:582)
    at org.eclipse.jface.dialogs.ProgressMonitorDialog.run(ProgressMonitorDialog.java:498)
    at com.blah.si.workflow.SWTApplication.main(SWTApplication.java:135)

现在,使这个奇怪的事情:

Now, the things that make this odd:


  1. 当我更改项目构建路径并替换jface .jar with源项目(相同版本--3.3.1),错误消失。

  2. 我使用相同jar的其他应用程序,以及相同启动配置文件和项目的副本,所有工作正常。

  3. 这是一个 ClassNotFoundException 。该类位于类路径上。如果我将源附加到jar,我可以调试到getFontRegistry方法。该方法将成功执行几次,最后在第338行抛出 NoClassDefFoundError 。第337行是if variable == null语句,检查静态变量是否已被删除初始化。如果尚未初始化,则338行正在初始化它。第一次通过时,空检查失败,并执行初始化。在随后的方法传递中,null检查通过,因此返回已经初始化的静态值。在最后一次传递(失败的那个)上,null检查再次失败(即使静态变量已经初始化),当它尝试重新初始化静态变量时, NoClassDefFoundError 被抛出。这是相关的来源(从第336行开始,请注意,fontRegistry是一个私有静态变量,在其他任何地方都没有设置):

  1. When I change the project build path and replace jface.jar with the source project (same version - 3.3.1), the error goes away.
  2. Other applications I have that use the same jar, and a copy of the same launch profile and project, all works fine.
  3. This is NOT a ClassNotFoundException. The class is on the classpath. If I attach source to the jar, I can debug into the getFontRegistry method. The method will execute successfully several times before eventually throwing a NoClassDefFoundError on line 338. Line 337 is a "if variable == null" statement checking to see if a static variable has been initialized. Line 338 is initializing it if it is not already initialized. The first time through, the null check fails, and the initialization is performed. On subsequent passes through the method, the null check passes, and thus the already-initialized static value is returned. On the final pass (the one that fails,) the null check fails again (even though the static variable has already been initialized) and when it tries to re-initialize the static variable, the NoClassDefFoundError is thrown. Here is the relevant source (starting with line 336, note that fontRegistry is a private static variable that is set in no other place):

public static FontRegistry getFontRegistry() {
   if (fontRegistry == null) {
     fontRegistry = new FontRegistry(
         "org.eclipse.jface.resource.jfacefonts");
   }
   return fontRegistry;
}


  1. 我已经获得了jar的新副本(以确保它没有被破坏),删除了我的.classpath和.project文件并启动了一个新项目,并重新创建了启动配置文件。没有变化。

由于上面#3的特殊性,我怀疑某种奇怪的类加载器行为 - 似乎好像最终通过该方法是在另一个类加载器?

Because of the peculiarities in #3 above, I'm suspecting some kind of wierd classloader behavior - it seems as if that final pass through the method is in another classloader?

想法?

更新: Pourquoi Litytestdata提供的答案促使我注意在ProgressMonitorDialog第458行上方的try块中发生的事情。实际上,该代码抛出了一个异常,它被finally块吞噬了。根本原因是另一个缺少类(缺少的类不是JFontRegistry或其任何直接相关的类,而是另一个在边缘情况下依赖于蜘蛛网的。)我正在推荐所有回答指向我注意类路径,并接受Pourquoi的,因为这是突破。谢谢大家。

Update: The answer provided by Pourquoi Litytestdata prompted me to pay attention to what happens in the try block just above line 458 of ProgressMonitorDialog. Indeed, that code was throwing an exception, which was being gobbled by the finally block. The root cause was ANOTHER missing class (the missing class was not JFontRegistry or any of its directly related classes, but another that was spider-web dependencied in an edge case.) I'm upvoting all answers pointing me to pay attention to the classpath, and accepting Pourquoi's, because it was the breakthrough. Thanks to all.

推荐答案

我认为上面介绍的堆栈跟踪隐藏了真正的问题。以下是
中方法运行中的代码 org.eclipse.jface.dialogs.ProgressMonitorDialog (我添加评论):

I think the stacktrace presented above is concealing the real problem here. Below is the code in the method run within org.eclipse.jface.dialogs.ProgressMonitorDialog (with a comment added by me):

public void run(boolean fork, boolean cancelable,
         IRunnableWithProgress runnable) throws InvocationTargetException,
         InterruptedException {
     setCancelable(cancelable);
     try {
         aboutToRun();
         // Let the progress monitor know if they need to update in UI Thread
         progressMonitor.forked = fork;
         ModalContext.run(runnable, fork, getProgressMonitor(), getShell()
                 .getDisplay());
     } finally {
         finishedRun();  // this is line 498
     }
}

第二个来自 - Jared的stacktrace的底线是这个类的第498行,它是 finally 块中对 finishedRun()的调用。我怀疑真正的原因是在 try 块中抛出异常。由于 finally 块中的代码也会抛出异常,原始异常将丢失。

The second-from-bottom line in Jared's stacktrace is line 498 of this class, which is the call to finishedRun() within the finally block. I suspect that the real cause is an exception being thrown in the try block. Since the code in the finally block also throws an exception, the original exception is lost.

这篇关于JFace FontRegistry上的NoClassDefFoundError的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆