首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >NoClassDefFoundError on JFace FontRegistry

NoClassDefFoundError on JFace FontRegistry
EN

Stack Overflow用户
提问于 2009-02-27 22:55:29
回答 4查看 2.7K关注 0票数 3

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

代码语言:javascript
复制
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)

现在,让这一切变得奇怪的事情:

  1. 当我更改项目构建路径并将jface.jar替换为源项目(相同版本- 3.3.1)时,错误就会消失。
  2. 其他使用相同jar的应用程序,以及相同的启动配置文件和项目的副本,都可以正常工作。
  3. 这是而不是a ClassNotFoundException。这门课在类路径上。如果将源代码附加到jar,则可以调试到getFontRegistry方法中。在最终将NoClassDefFoundError抛出到第338行之前,该方法将成功执行几次。第337行是"if变量== null“语句,检查静态变量是否已初始化。如果尚未初始化,则行338正在对其进行初始化。第一次,空检查失败,并执行初始化。在随后通过该方法时,将传递空检查,从而返回已初始化的静态值。在最后一次传递时(失败的那个),空检查再次失败(即使静态变量已经初始化),并且当它尝试重新初始化静态变量时,会抛出NoClassDefFoundError。下面是相关的源(从第336行开始,请注意,fontRegistry是一个私有静态变量,没有在其他地方设置):

代码语言:javascript
复制
public static FontRegistry getFontRegistry() {
   if (fontRegistry == null) {
     fontRegistry = new FontRegistry(
         "org.eclipse.jface.resource.jfacefonts");
   }
   return fontRegistry;
}

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

由于上面#3中的特性,我怀疑某种wierd类加载器的行为--似乎这个方法的最后通过是在另一个类加载器中?

想法?

更新:-- Litytestdata提供的答案促使我注意ProgressMonitorDialog第458行上方的ProgressMonitorDialog块发生了什么。实际上,该代码正在抛出一个异常,这个异常正在被finally块吞噬。根本原因是另一个缺少的类(缺少的类不是JFontRegistry或它的任何直接相关的类,而是在边缘情况下依赖于蜘蛛网的另一个类)。我正在整理所有的答案,指出我要注意类路径,接受普尔魁的,因为这是一个突破。多亏了所有人。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2009-02-28 13:11:01

我认为上面提到的堆栈跟踪掩盖了这里的真正问题。下面是方法runorg.eclipse.jface.dialogs.ProgressMonitorDialog中的代码(我添加了一个注释):

代码语言:javascript
复制
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的堆栈跟踪中的第二行是这个类的第498行,它是对finishedRun()finally块中的调用。我怀疑真正的原因是在try块中抛出的异常。由于finally块中的代码也会引发异常,因此原始异常将丢失。

票数 2
EN

Stack Overflow用户

发布于 2009-02-28 09:18:53

听起来好像缺少了一个包含依赖项的JAR文件,正如桑吉夫·吉文在2006年7月的博客文章中提到的那样:

ClassNotFoundException与NoClassDefFoundError的区别

当报告的类未被ClassNotFoundException找到时,将引发ClassLoader。 这通常意味着类从CLASSPATH中丢失。 这也可能意味着所讨论的类试图从另一个类中加载,这个类是在父ClassLoader中加载的,因此子ClassLoader中的类不可见。 在像App这样更复杂的环境中工作时,有时也会出现这种情况(WebSphere因ClassLoader问题而臭名昭著)。 人们往往会把java.lang.NoClassDefFoundErrorjava.lang.ClassNotFoundException混为一谈。然而,有一个重要的区别。 例如,一个异常(实际上是一个错误,因为java.lang.NoClassDefFoundErrorjava.lang.Error)的一个子类,如

代码语言:javascript
复制
java.lang.NoClassDefFoundError:
org/apache/activemq/ActiveMQConnectionFactory

并不意味着ActiveMQConnectionFactory类不在CLASSPATH中。 事实上,情况正好相反。 它意味着类ActiveMQConnectionFactory ClassLoader 是由ClassLoader找到的,但是当试图加载类时,它在读取类定义时遇到了错误。 这种情况通常发生在所讨论的类具有静态块或成员时,这些静态块或成员使用的类不是由ClassLoader**.找到的 因此,要找到罪魁祸首,请查看所讨论类的源(本例中为ActiveMQConnectionFactory),使用静态块或静态成员查找代码。 如果您无法访问源,那么只需使用[JAD**](http://www.kpdus.com/jad.html)对其进行反编译。 在检查代码时,假设您找到如下所示的一行代码,请确保SomeClass类在您的CLASSPATH中。

代码语言:javascript
复制
private static SomeClass foo = new SomeClass();

提示:要找出一个类属于哪个jar,可以使用网站jarFinder。这允许您使用通配符指定类名,并在其jars数据库中搜索该类。 扎尔胡允许您做同样的事情,但它不再免费使用。 如果希望在本地路径中找到类所属的哪个jar,可以使用像扎尔桑这样的实用程序。您只需指定要定位的类以及希望它开始在jars和zip文件中搜索类的根目录路径。

票数 3
EN

Stack Overflow用户

发布于 2009-03-02 02:52:36

要更好地处理如果是类加载程序问题,请遍历它工作的代码并添加:

代码语言:javascript
复制
try
{
    final Class       clazz;
    final ClassLoader loader;

    clazz  = Class.forName("org/eclipse/jface/resource/FontRegistry");
    loader = clazz.getClassLoader(); 
    System.out.println("The classloader at step 1 is: " + loader);
}
catch(final Throwable ex)
{
    ex.printStackTrace();
}

然后在获取NoClassDefFoundError的地方做同样的事情,看看类加载器是否不同。

然后,您将能够确保不同的是ClassLoader。你能报告一下这个发生了什么吗?取决于结果,我可能会有更多的想法。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/596999

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档