当我启动SWT应用程序(通过Eclipse启动配置文件)时,我收到以下堆栈跟踪:
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)现在,让这一切变得奇怪的事情:
ClassNotFoundException。这门课在类路径上。如果将源代码附加到jar,则可以调试到getFontRegistry方法中。在最终将NoClassDefFoundError抛出到第338行之前,该方法将成功执行几次。第337行是"if变量== null“语句,检查静态变量是否已初始化。如果尚未初始化,则行338正在对其进行初始化。第一次,空检查失败,并执行初始化。在随后通过该方法时,将传递空检查,从而返回已初始化的静态值。在最后一次传递时(失败的那个),空检查再次失败(即使静态变量已经初始化),并且当它尝试重新初始化静态变量时,会抛出NoClassDefFoundError。下面是相关的源(从第336行开始,请注意,fontRegistry是一个私有静态变量,没有在其他地方设置):。
public static FontRegistry getFontRegistry() {
if (fontRegistry == null) {
fontRegistry = new FontRegistry(
"org.eclipse.jface.resource.jfacefonts");
}
return fontRegistry;
}。
由于上面#3中的特性,我怀疑某种wierd类加载器的行为--似乎这个方法的最后通过是在另一个类加载器中?
想法?
更新:-- Litytestdata提供的答案促使我注意ProgressMonitorDialog第458行上方的ProgressMonitorDialog块发生了什么。实际上,该代码正在抛出一个异常,这个异常正在被finally块吞噬。根本原因是另一个缺少的类(缺少的类不是JFontRegistry或它的任何直接相关的类,而是在边缘情况下依赖于蜘蛛网的另一个类)。我正在整理所有的答案,指出我要注意类路径,接受普尔魁的,因为这是一个突破。多亏了所有人。
发布于 2009-02-28 13:11:01
我认为上面提到的堆栈跟踪掩盖了这里的真正问题。下面是方法run在org.eclipse.jface.dialogs.ProgressMonitorDialog中的代码(我添加了一个注释):
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块中的代码也会引发异常,因此原始异常将丢失。
发布于 2009-02-28 09:18:53
听起来好像缺少了一个包含依赖项的JAR文件,正如桑吉夫·吉文在2006年7月的博客文章中提到的那样:
ClassNotFoundException与NoClassDefFoundError的区别
当报告的类未被
ClassNotFoundException找到时,将引发ClassLoader。 这通常意味着类从CLASSPATH中丢失。 这也可能意味着所讨论的类试图从另一个类中加载,这个类是在父ClassLoader中加载的,因此子ClassLoader中的类不可见。 在像App这样更复杂的环境中工作时,有时也会出现这种情况(WebSphere因ClassLoader问题而臭名昭著)。 人们往往会把java.lang.NoClassDefFoundError和java.lang.ClassNotFoundException混为一谈。然而,有一个重要的区别。 例如,一个异常(实际上是一个错误,因为java.lang.NoClassDefFoundError是java.lang.Error)的一个子类,如
java.lang.NoClassDefFoundError:
org/apache/activemq/ActiveMQConnectionFactory并不意味着ActiveMQConnectionFactory类不在
CLASSPATH中。 事实上,情况正好相反。 它意味着类ActiveMQConnectionFactoryClassLoader是由ClassLoader找到的,但是当试图加载类时,它在读取类定义时遇到了错误。 这种情况通常发生在所讨论的类具有静态块或成员时,这些静态块或成员使用的类不是由ClassLoader**.找到的 因此,要找到罪魁祸首,请查看所讨论类的源(本例中为ActiveMQConnectionFactory),使用静态块或静态成员查找代码。 如果您无法访问源,那么只需使用[JAD**](http://www.kpdus.com/jad.html)对其进行反编译。 在检查代码时,假设您找到如下所示的一行代码,请确保SomeClass类在您的CLASSPATH中。
private static SomeClass foo = new SomeClass();提示:要找出一个类属于哪个jar,可以使用网站jarFinder。这允许您使用通配符指定类名,并在其jars数据库中搜索该类。 扎尔胡允许您做同样的事情,但它不再免费使用。 如果希望在本地路径中找到类所属的哪个jar,可以使用像扎尔桑这样的实用程序。您只需指定要定位的类以及希望它开始在jars和zip文件中搜索类的根目录路径。
发布于 2009-03-02 02:52:36
要更好地处理如果是类加载程序问题,请遍历它工作的代码并添加:
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。你能报告一下这个发生了什么吗?取决于结果,我可能会有更多的想法。
https://stackoverflow.com/questions/596999
复制相似问题