当我启动 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)
现在,让这变得奇怪的事情:
- 当我更改项目构建路径并将 jface.jar 替换为源项目(相同版本 - 3.3.1)时,错误消失了。
- 我拥有的其他应用程序使用相同的 jar,以及相同启动配置文件和项目的副本,一切正常。
- 这不是一个
ClassNotFoundException
. 该类位于类路径上。如果我将源附加到 jar,我可以调试到 getFontRegistry 方法。该方法将成功执行几次,然后最终NoClassDefFoundError
在第 338 行抛出一个。第 337 行是一个“if variable == null”语句,用于检查静态变量是否已被初始化。如果它尚未初始化,第 338 行正在初始化它。第一次通过,空检查失败,进行初始化。在随后通过该方法时,空检查通过,因此返回已经初始化的静态值。在最后一次通过(失败的那一次)时,空值检查再次失败(即使静态变量已经初始化),当它尝试重新初始化静态变量时,NoClassDefFoundError
被抛出。这是相关的源代码(从第 336 行开始,注意 fontRegistry 是一个私有静态变量,没有在其他地方设置):
.
public static FontRegistry getFontRegistry() {
if (fontRegistry == null) {
fontRegistry = new FontRegistry(
"org.eclipse.jface.resource.jfacefonts");
}
return fontRegistry;
}
.
- 我已经获得了 jar 的新副本(以确保它没有损坏),删除了我的 .classpath 和 .project 文件并开始了一个新项目,并重新创建了启动配置文件。不用找了。
由于上面 #3 中的特殊性,我怀疑某种奇怪的类加载器行为 - 似乎最终通过该方法的方法是在另一个类加载器中?
想法?
更新: Pourquoi Litytestdata 提供的答案提示我注意在 ProgressMonitorDialog 的第 458 行上方的 try 块中发生了什么。实际上,该代码正在引发异常,该异常正在被 finally 块吞噬。根本原因是另一个缺失的类(缺失的类不是 JFontRegistry 或其任何直接相关的类,而是另一个在边缘情况下依赖于蜘蛛网的类。)我赞成所有答案,指出我要注意类路径,并接受 Pourquoi 的,因为这是突破。谢谢大家。