我've tried both the example in Oracle' s Java Tutorials . 它们都编译得很好,但在运行时,都会出现这个错误:
Exception in thread "main" java.lang.NoClassDefFoundError: graphics/shapes/Square
at Main.main(Main.java:7)
Caused by: java.lang.ClassNotFoundException: graphics.shapes.Square
at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 1 more
我想我可能在错误的文件夹中有 Main.java
文件 . 这是目录层次结构:
graphics
├ Main.java
├ shapes
| ├ Square.java
| ├ Triangle.java
├ linepoint
| ├ Line.java
| ├ Point.java
├ spaceobjects
| ├ Cube.java
| ├ RectPrism.java
这是 Main.java
:
import graphics.shapes.*;
import graphics.linepoint.*
import graphics.spaceobjects.*;
public class Main {
public static void main(String args[]) {
Square s = new Square(2,3,15);
Line l = new Line(1,5,2,3);
Cube c = new Cube(13,32,22);
}
}
我在这做错了什么?
UPDATE
在我把 Main
类放入 graphics
包(我添加了 package graphics;
)后,将类路径设置为"_test"(包含图形的文件夹),编译它,并使用 java graphics.Main
(从命令行)运行它,它工作 .
Really late UPDATE #2
我没有使用Eclipse(只是Notepad和JDK),上面的更新解决了我的问题 . 但是,似乎许多这些答案都适用于Eclipse和IntelliJ,但它们具有相似的概念 .
22 回答
编译代码后,最终会为程序中的每个类生成
.class
个文件 . 这些二进制文件是Java解释执行程序的字节码 .NoClassDefFoundError
表示负责动态加载类的类加载器(在本例中为java.net.URLClassLoader
)无法找到您尝试使用的类的.class
文件 .您的代码不会出现(除非使用反射加载类),因此通常此异常意味着您的类路径不包含所需的类 . 请记住,类加载器(特别是
java.net.URLClassLoader
)将在类路径的每个条目中的文件夹a / b / c /中查找包a.b.c中的类 .NoClassDefFoundError
也可以表示您编译了're missing a transitive dependency of a .jar file that you',并且您正在尝试使用 .例如,如果您有一个类
com.example.Foo
,则在编译之后您将拥有一个类文件Foo.class
. 比如说你的工作目录是.../project/
. 该类文件必须放在.../project/com/example
中,您可以将类路径设置为.../project/
.旁注:我建议利用Java和JVM语言中存在的神奇工具 . 现代IDE就像Eclipse和IDEA以及构建管理工具(如Maven或Gradle)将帮助您不必担心类路径(尽可能多)并专注于代码!也就是说,this link解释了在命令行上执行时如何设置类路径 .
我想在
NoClassDefFoundError
上纠正别人的观点 .NoClassDefFoundError
可能由于多种原因而发生ClassNotFoundException - 找不到该引用类的.class,无论它是否在编译时可用(即base / child class) .
找到类文件,但在初始化静态变量时引发了异常
找到类文件,初始化静态块时引发异常
在最初的问题中,这是第一个可以通过将CLASSPATH设置为引用的类jar文件或其包文件夹来纠正的情况 .
说"available in compile time"是什么意思?
例如:两个类,A和B(扩展A) . 如果在代码中直接引用B,则它在编译时可用,即A a = new B();
说“编译时不可用”是什么意思?
例如:两个类,A和B(扩展A) . 代码有
A = Class.forName("B") . newInstance();
NoClassDefFoundError
表示该类存在于Compile time
的类路径中,但它在Runtime
的类路径中不存在 .如果您正在使用Eclipse,请确保
shapes
,linepoints
和spaceobjects
作为.classpath
文件中的条目 .如果您在编译和运行时遇到以下错误之一:
-------------------------- SOLUTIION -----------------------
the problem is mostly in packages organization. You should arrange your classes in folders properly regarding to the package classifications in your source code.
表示在编译时发现了某些内容但在运行时未发现 . 也许你只需要将它添加到类路径中 .
当在类路径中找不到目标类时,会出现 No Class Definition Exception . 在编译时类:从Java编译器生成类,但在运行时以某种方式找不到从属类 .
让我们来看一个简单的例子:
}
现在让我们假设上面两个Java源代码放在一些文件夹中,让我们说“NoClassDefinationFoundExceptionDemo”
现在打开一个shell(假设Java已经正确设置)
转到文件夹"NoClassDefinationFoundExceptionDemo"
编译Java源文件javac ClassB javac ClassA
两个文件都是成功编译的,并且在与ClassA.class和ClassB.class相同的文件夹中生成了类文件
现在由于我们将ClassPath重写为当前工作目录,因此我们执行以下命令 java -cp . ClassA 并且它成功运行,您将在屏幕上看到输出
现在让我们说,您从Present Directory中删除了ClassB.class文件 . 现在你再次执行命令 . java -cp . ClassA 现在它会用NoClassDefFoundException来迎接你 . 因为在类路径(即当前工作目录)中找不到作为ClassA依赖关系的ClassB .
如果您的项目位于
com.blahcode
之类的包中,并且您的类名为Main
,则编译的文件可能会在./out/com/blahcode/Main.class
之类的目录结构中输出 . 对于IntelliJ IDEA尤其如此 .尝试从shell或cmd运行时,需要
cd
到包含com
的子目录 .NoClassDefFoundError in Java:
Definition:
如果在编译期间存在类但在运行时期间在java类路径中不可用,则会出现NoClassDefFoundError . 当你得到NoClassDefFoundError时,通常会在日志中看到下面一行:线程“main”中的异常java.lang.NoClassDefFoundError
Possible Causes:
该类在Java Classpath中不可用 .
您可能正在使用jar命令运行程序,并且未在清单文件的ClassPath属性中定义类 .
任何启动脚本都会覆盖Classpath环境变量 .
因为NoClassDefFoundError是java.lang.LinkageError的子类,所以如果其中一个依赖项(如本机库)可能不可用,也会出现这种情况 .
检查日志文件中的java.lang.ExceptionInInitializerError . 由于静态初始化失败而导致的NoClassDefFoundError非常常见 .
如果您在J2EE环境中工作,那么多个Classloader中的Class的可见性也会导致java.lang.NoClassDefFoundError,请参阅示例和场景部分进行详细讨论 .
Possible Resolutions:
验证应用程序的类路径中是否包含所有必需的Java类 . 在开始执行依赖于某些外部库的Java应用程序之前,最常见的错误是不包括所有必需的类 .
应用程序的类路径是正确的,但在应用程序执行之前会覆盖Classpath环境变量 .
验证上述ExceptionInInitializerError未出现在应用程序的堆栈跟踪中 .
Resources:
3 ways to solve java.lang.NoClassDefFoundError in Java J2EE
java.lang.NoClassDefFoundError – How to solve No Class Def Found Error
我今天遇到了这个问题 . 我有一个Android项目,启用
multidex
后,项目将不再启动 .原因是我忘记调用应该添加到
Application class
的特定multidex方法,并在其他所有方法之前调用 .按照本教程正确启用multidex . https://developer.android.com/studio/build/multidex.html
您应该将这些行添加到Application类中
在处理NetBeans项目数月后,我在收到“低内存”警报后不久就突然收到NoClassDefFoundError消息 . 做一个干净的重建没有帮助,但完全关闭Netbeans并重新打开项目没有错误报告 .
这个答案特定于服务中发生的java.lang.NoClassDefFoundError:
我的团队最近在升级提供服务的rpm后看到了这个错误 . rpm和它内部的软件都是用Maven构建的,所以我们似乎有一个编译时依赖项,而这个依赖项还没有包含在rpm中 .
但是,在调查时,未找到的类与堆栈跟踪中的几个类位于同一模块中 . 此外,这不是最近才添加到构建中的模块 . 这些事实表明它可能不是Maven依赖问题 .
最终的解决方案: Restart the service!
似乎rpm升级使基础jar文件上的服务文件句柄无效 . 然后,该服务看到一个尚未加载到内存中的类,在其jar文件句柄列表中搜索它,并且找不到它,因为它可以加载类的文件句柄已经失效 . 重新启动服务会强制它重新加载所有文件句柄,然后允许它在rpm升级后加载那个在内存中找不到的类 .
希望具体案例有助于某人 .
我在这个链中的两分钱:
确保 classpath 包含 full 路径(
/home/user/lib/some_lib.jar
而不是~/lib/some_lib.jar
),否则您仍然可能会遇到NoClassDefFoundError
错误 .当运行时类加载器加载的类无法访问java rootloader已经加载的类时,我得到NoClassFoundError . 因为不同的类加载器位于不同的安全域中(根据java),jvm将不允许在运行时加载器地址空间中解析已由rootloader加载的类 .
用'java -javaagent:tracer.jar [你的java ARGS]'运行你的程序
它生成显示已加载类的输出,以及加载类的加载器env . 这非常有用,可以追踪无法解决课程的原因 .
我的genymotion设备发生了很多事情 . 确保安装了Genymotion的驱动器上有足够的可用内存 .
它发生在我的Android Studio中 .
对我有用的解决方案:重启工作室 .
使用Android studio进行Android开发时遇到了同样的问题 . 提供的解决方案是一般的,并没有帮助我(至少对我来说) . 经过几个小时的研究后,我找到了以下解决方案,可能对使用android studio进行开发的android开发人员有所帮助 . 修改设置,如下面的首选项 - >构建,执行,部署 - >即时运行 - >取消选中第一个选项 .
有了这个改变,我就开始了 . 希望这能帮助我的开发朋友 .
此异常的一个错误来源可能源于Proguard的定义不一致,例如:一个失踪
-libraryJars“path.to.a.missing.jar.library” .
这解释了为什么编译和运行工作正常,因为jar在那里,而clean和build失败 . 记得在proguard设置中定义新添加的jar库!
请注意,来自Proguard的错误消息实际上不符合标准,因为它们很容易与 jar 根本不存在时到达的类似 Ant 消息混淆 . 只有在最底层才会出现一些麻烦的提示 . 因此,开始搜索传统的类路径错误等是非常逻辑的,但这将是徒劳的 .
显然,NoClassDefFound异常将是运行时的结果,例如生成的可执行jar是基于缺乏proguard一致性而构建的 . 有人称之为“地狱”
我使用FileSync plugin for Eclipse所以我可以在Tomcat上进行调试并收到了
NoClassFoundError
,因为我已经在metadata
中的Eclipse工作区=> classes
中为bin
目录添加了一个同步条目,但是还没有为extlib
目录添加文件夹同步Eclipse=>
C:\Users\Stuart\eclipse-workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\webapps\myApp\WEB-INF\lib
我正在开发一个基于Eclipse的应用程序,也称为 RCP (Rich Client Platform) . 重构后我一直面临这个问题(将一个类从一个插件移到一个新的) .
清理项目和Maven更新没有帮助 .
该问题是由 Bundle-Activator 引起的,它没有自动更新 . 在新的PlugIn中手动更新 MANIFEST.MF 下的Bundle-Activator解决了我的问题 .
如果您最近在android studio中添加了multidex支持,如下所示:
因此,您的解决方案只是从MultiDexApplication而不是Application扩展
如果您使用多个模块,则应该使用
在您的构建文件中 .
如果您的 class 中有静态处理程序,请检查如果是这样,请小心,因为静态处理程序只能在具有looper的线程中启动,崩溃可以通过这种方式触发:
1.首先,在一个简单的线程中创建类的实例并捕获崩溃 .
2.然后在主线程中调用Class的field方法,你将获得NoClassDefFoundError .
这是测试代码:
在主要活动的onCrete方法中,添加测试代码部分:
有一个简单的方法来修复它使用handlerThread到init处理程序: