我在Oracle的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);
}
}
我在这里做错了什么?
更新
在我将Main
类放入graphics
包(我向其添加package graphics;
)后,将类路径设置为“_test”(包含图形的文件夹),编译它,并使用java graphics.Main
(从命令行)运行它,它工作。
最近更新#2
我没有使用Eclipse(只是Notepad ++和JDK),上面的更新解决了我的问题。但是,似乎许多这些答案都是针对Eclipse和IntelliJ的,但它们有类似的概念。
答案 0 :(得分:193)
编译代码后,最终会为程序中的每个类生成.class
个文件。这些二进制文件是Java解释执行程序的字节码。 NoClassDefFoundError
表示负责动态加载类的类加载器(在本例中为java.net.URLClassLoader
)无法找到您尝试使用的类的.class
文件。
如果不存在所需的类(除非使用反射加载类),您的代码将无法编译,因此通常此异常意味着您的类路径不包含所需的类。请记住,类加载器(特别是java.net.URLClassLoader
)将在类路径的每个条目中的文件夹a / b / c /中查找包a.b.c中的类。 NoClassDefFoundError
还可以表明您错过了您编译过的.jar文件的传递依赖项,并且您尝试使用该文件。
例如,如果您有一个类com.example.Foo
,那么在编译之后您将拥有一个类文件Foo.class
。比如说你的工作目录是.../project/
。该类文件必须放在.../project/com/example
中,您可以将类路径设置为.../project/
。
旁注:我建议利用Java和JVM语言存在的神奇工具。现代IDE就像Eclipse和IDEA以及构建管理工具(如Maven或Gradle)将帮助您不必担心类路径(尽可能多)并专注于代码!也就是说,this link解释了在命令行上执行时如何设置类路径。
答案 1 :(得分:117)
我想在NoClassDefFoundError
上更正其他人的观点。
NoClassDefFoundError
可能由于多种原因而发生,例如
在最初的问题中,这是第一个可以通过将CLASSPATH设置为引用的类jar文件或其包文件夹来纠正的情况。
说“编译时可用”是什么意思?
说“编译时不可用”是什么意思?
答案 2 :(得分:12)
NoClassDefFoundError
表示该类存在于Compile time
的类路径中,但它不存在于Runtime
的类路径中。
如果您使用的是Eclipse,请确保shapes
文件中包含linepoints
,spaceobjects
和.classpath
作为条目。
答案 3 :(得分:11)
如果在编译和运行时遇到其中一个错误:
* NoClassDefFoundError
* Error: Could not find or load main class hello
* Exception in thread "main" java.lang.NoClassDefFoundError:javaTest/test/hello
(wrong name: test/hello)
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(Unknown Source)
at java.security.SecureClassLoader.defineClass(Unknown Source)
at java.net.URLClassLoader.defineClass(Unknown Source)
at java.net.URLClassLoader.access$100(Unknown Source)
at java.net.URLClassLoader$1.run(Unknown Source)
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.launcher.LauncherHelper.checkAndLoadMain(Unknown Source)
-------------------------- SOLUTIION ------ -----------------
问题主要出在包装组织中。您应该在文件夹中正确安排有关源代码中的包分类的类。
On Compiling process use this command:
javac -d . [FileName.java]
To Run the class please use this command:
java [Package].[ClassName]
答案 4 :(得分:8)
java.lang.NoClassDefFoundError
表示在 compiletime 但未在运行时找到了某些内容。也许你只需要将它添加到类路径中。
答案 5 :(得分:6)
没有类定义异常。 在编译时类:类是从Java编译器生成的,但不知何故 在运行时,找不到依赖类。
让我们看一个简单的例子:
public class ClassA{
public static void main(String args[]){
//Some gibberish Code...
String text = ClassB.getString();
System.out.println("Text is :" + text);
}
}
public class ClassB{
public static String getString(){
return "Testing Some Exception";
}
}
现在让我们假设上面两个Java源代码放在一些文件夹中,让我们说“NoClassDefinationFoundExceptionDemo”
现在打开一个shell(假设Java已经正确设置)
答案 6 :(得分:2)
如果您的项目位于com.blahcode
之类的包中,并且您的类名为Main
,则编译后的文件可能会在./out/com/blahcode/Main.class
这样的目录结构中输出。对于IntelliJ IDEA尤其如此。
尝试从shell或cmd运行时,需要cd
到包含com
的子目录。
cd out
java -classpath . com.blahcode.Main
答案 7 :(得分:2)
Java中的NoClassDefFoundError:
定义:
如果在编译期间存在类但在运行时期间在java类路径中不可用,则会出现NoClassDefFoundError。通常,当您获得NoClassDefFoundError时,您将在日志中看到以下行: 线程" main"中的例外情况java.lang.NoClassDefFoundError
可能的原因:
该类在Java Classpath中不可用。
您可能正在使用jar命令运行程序,并且未在清单文件的ClassPath属性中定义类。
任何启动脚本都会覆盖Classpath环境变量。
因为NoClassDefFoundError是java.lang.LinkageError的子类,所以如果其中一个依赖项(如本机库)可能不可用,它也会出现。
检查日志文件中的java.lang.ExceptionInInitializerError。由于静态初始化失败而导致的NoClassDefFoundError非常常见。
如果您在J2EE环境中工作,而多个Classloader中的Class的可见性也会导致java.lang.NoClassDefFoundError,请参阅示例和场景部分以进行详细讨论。
可能的解决方案:
验证应用程序的类路径中是否包含所有必需的Java类。在开始执行依赖于某些外部库的Java应用程序之前,最常见的错误是不包括所有必需的类。
应用程序的类路径是正确的,但在应用程序执行之前会覆盖Classpath环境变量。
验证上述ExceptionInInitializerError未出现在应用程序的堆栈跟踪中。
资源:
3 ways to solve java.lang.NoClassDefFoundError in Java J2EE
java.lang.NoClassDefFoundError – How to solve No Class Def Found Error
答案 8 :(得分:1)
对于我的项目,解决问题的是Chrome浏览器和chromedriver不兼容。我的驱动程序版本太旧,甚至无法打开浏览器。我刚刚下载了两者的最新版本,并解决了问题。我是如何发现问题的?因为我使用Selenium本机firefox驱动程序运行了项目,并且将旧版本的FF与我的应用程序结合在一起,所以我意识到问题出在浏览器和驱动程序之间不兼容。
希望这可以帮助任何与我类似的问题并产生相同错误消息的人。
答案 9 :(得分:1)
我今天遇到了这个问题。我有一个Android项目,在启用multidex
后,该项目将不再启动。
原因是我忘记调用应添加到Application class
并在其他所有内容之前调用的特定multidex方法。
MultiDex.install(this);
按照本教程正确启用multidex。 https://developer.android.com/studio/build/multidex.html
您应该将这些行添加到Application类
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
MultiDex.install(this);
}
答案 10 :(得分:1)
在处理NetBeans项目好几个月之后,我在收到“低内存”警报后不久就突然收到NoClassDefFoundError消息。做一个干净的重建没有帮助,但完全关闭Netbeans并重新打开项目没有错误报告。
答案 11 :(得分:1)
此答案特定于服务中发生的java.lang.NoClassDefFoundError:
我的团队最近在升级提供服务的rpm后看到了这个错误。 rpm和它内部的软件都是用Maven构建的,所以我们似乎有一个编译时依赖项,而这个依赖项还没有包含在rpm中。
但是,在调查时,未找到的类与堆栈跟踪中的几个类位于同一模块中。此外,这不是最近才添加到构建中的模块。这些事实表明它可能不是Maven依赖问题。
最终解决方案:重新启动服务!
rpm升级似乎使基础jar文件上的服务文件句柄无效。然后,该服务看到一个尚未加载到内存中的类,在其jar文件句柄列表中搜索它,并且找不到它,因为它可以加载类的文件句柄已经失效。重新启动服务会强制它重新加载所有文件句柄,然后允许它在rpm升级后加载那个在内存中找不到的类。
希望具体案例有助于某人。
答案 12 :(得分:0)
如果您最近在Android studio中添加了multidex支持,请执行以下操作:
// To Support MultiDex
implementation 'com.android.support:multidex:1.0.1'
所以你的解决方案只是从MultiDexApplication而不是Application
扩展public class MyApp extends MultiDexApplication {
答案 13 :(得分:0)
如果您要从 JAR 文件“启动”一个类,请确保以 JAR 完整路径开头。例如,(如果您的“主类”未在清单中指定):
java -classpath "./dialer.jar" com.company.dialer.DialerServer
并且如果有任何依赖,比如对其他JAR文件的依赖,你可以解决这样的依赖
java -classpath "./libs/phone.jar;./libs/anotherlib.jar;./dialer.jar" com.company.dialer.DialerServer
Manifest-Version: 1.0
Class-Path: phone.jar anotherlib.jar
Build-Jdk-Spec: 1.8
Main-Class: com.company.dialer.DialerServer
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>com.company.dialer.DialerServer</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
请注意,上面的示例使用 ;
作为 classpath 中的分隔符(它对 Windows 平台有效)。在 Linux 上,将 ;
替换为 :
。
例如
java -classpath ./libs/phone.jar:./libs/anotherlib.jar:./dialer.jar
com.company.dialer.DialerServer
答案 14 :(得分:0)
我没有解决方案,只是“编译时存在,运行时不存在”情况的另一种形式。
我试图使用JUnit测试类中另一个驻留在不同模块中的测试类中非常方便的方法。这是不可以的,因为测试代码不是打包的jar的一部分,但是我没有意识到,因为它对于Eclipse中的用户类而言是可见的。
我的解决方案是将该方法放在生产代码中的现有实用程序类中。
答案 15 :(得分:0)
在我的环境中,我在单元测试中遇到此问题。将一个库依赖项附加到* .pom之后,此问题已解决。
例如:
错误消息:
java.lang.NoClassDefFoundError: com/abc/def/foo/xyz/Iottt
pom:
<dependency>
<groupId>com.abc.def</groupId>
<artifactId>foo</artifactId>
<scope>test</scope>
</dependency>
答案 16 :(得分:0)
更改Git分支后出现此错误。对于Eclipse的特定情况,org.eclipse.wst.common.component文件的.settings目录中缺少行。如您所见
使用Maven Install恢复项目依赖项会有所帮助。
答案 17 :(得分:0)
如果您使用的是gradlew
,请转到./gradle/wrapper/gradle-wrapper.properties
并将distributionUrl
更改为正确的gradle版本。
如果您使用的是JDK14,请尝试
distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-bin.zip
答案 18 :(得分:0)
这可能是由您使用的 Java 版本引起的。对于 Meteor 和 Cordova,暂时坚持使用版本 8。
检查可用的 Java 版本 /usr/libexec/java_home -V
并查找 Java 版本 8 的路径名
设置 Java 版本 8 的路径
export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_191.jdk/Contents/Home
检查是否完成
echo $JAVA_HOME
继续编码。
答案 19 :(得分:0)
此错误意味着您没有添加某些依赖项。
答案 20 :(得分:0)
Java 11 + Eclipse 解决方案:
如果您没有在 Eclipse 项目中使用 module-info.java
,并且您手动添加了 JAR 文件而不是使用 Maven/Gradle,则此解决方案适合您。
更多信息在 In Eclipse, what is the difference between modulepath and classpath?。
答案 21 :(得分:0)
我正在开发一个基于Eclipse的应用程序,也称为 RCP(富客户端平台)。 重构后我一直面临这个问题(将一个类从一个插件移到一个新的插件中)。
清理项目和Maven更新没有帮助。
问题是由 Bundle-Activator 引起的,它没有自动更新。在新的PlugIn中手动更新 MANIFEST.MF 下的Bundle-Activator修复了我的问题。
答案 22 :(得分:0)
我使用所以我可以在Tomcat&amp;我收到了NoClassFoundError
,因为我在Tomcat bin
的Eclipse工作区=> classes
中添加了metadata
目录的同步条目,但还没有添加文件夹同步Eclipse extlib
=>
目录
C:\Users\Stuart\eclipse-workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\webapps\myApp\WEB-INF\lib
答案 23 :(得分:0)
此异常的一个错误来源可能源于Proguard的定义不一致,例如:缺少
-libraryJars“path.to.a.missing.jar.library”。
这解释了为什么编译和运行工作正常,因为罐子在那里,而干净&amp;构建失败。记得在proguard设置中定义新添加的jar库!
请注意,来自Proguard的错误消息实际上不符合标准,因为它们很容易与罐子根本不存在时到达的类似ant消息混淆。只有在最底层才会出现一些麻烦的提示。因此,开始搜索传统的类路径错误等是非常逻辑的,但这将是徒劳的。
显然,NoClassDefFound异常将是运行时的结果,例如生成的可执行jar是基于缺乏proguard一致性而构建的。有人称它为“地狱”,而不是“地狱”
答案 24 :(得分:0)
如果您使用多个模块,则应该
dexOptions {
preDexLibraries = false
}
在您的构建文件中。
答案 25 :(得分:0)
检查您班级中是否有静态处理程序。如果是这样,请小心,因为静态处理程序只能在具有looper的线程中启动,崩溃可以通过这种方式触发:
1.首先,在一个简单的线程中创建类的实例并捕获崩溃。
2.然后在主线程中调用Class的field方法,你将获得NoClassDefFoundError。
这是测试代码:
public class MyClass{
private static Handler mHandler = new Handler();
public static int num = 0;
}
在主要活动的onCrete方法中,添加测试代码部分:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//test code start
new Thread(new Runnable() {
@Override
public void run() {
try {
MyClass myClass = new MyClass();
} catch (Throwable e) {
e.printStackTrace();
}
}
}).start();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
MyClass.num = 3;
// end of test code
}
有一种简单的方法可以使用handlerThread来修复它:init处理程序:
private static Handler mHandler;
private static HandlerThread handlerThread = new HandlerThread("newthread");
static {
handlerThread.start();
mHandler = new Handler(handlerThread.getLooper(), mHandlerCB);
}
答案 26 :(得分:0)
我使用Android studio进行Android开发时遇到了同样的问题。 提供的解决方案是一般的,并没有帮助我(至少对我来说)。 经过几个小时的研究后,我找到了以下解决方案,可能对使用android studio进行开发的android开发人员有所帮助。 修改设置如下 首选项 - &gt;构建,执行,部署 - &gt;即时运行 - &gt;取消检查第一个选项。
有了这个改变,我就开始了。 希望这能帮助我的开发朋友。
答案 27 :(得分:0)
Android Studio中发生了这件事。
对我有用的解决方案: 只需重新启动工作室。
答案 28 :(得分:0)
当运行时类加载器加载的类无法访问java rootloader已经加载的类时,我得到NoClassFoundError。因为不同的类加载器位于不同的安全域中(根据java),jvm不允许在运行时加载器地址空间中解析已由rootloader加载的类。
使用&#39; java -javaagent:tracer.jar运行您的程序[您的Java ARGS]&#39;
它生成显示已加载类的输出,以及加载类的加载器env。这是非常有用的追踪,为什么一个课程无法解决。
// ClassLoaderTracer.java
// From: https://blogs.oracle.com/sundararajan/entry/tracing_class_loading_1_5
import java.lang.instrument.*;
import java.security.*;
// manifest.mf
// Premain-Class: ClassLoadTracer
// jar -cvfm tracer.jar manifest.mf ClassLoaderTracer.class
// java -javaagent:tracer.jar [...]
public class ClassLoadTracer
{
public static void premain(String agentArgs, Instrumentation inst)
{
final java.io.PrintStream out = System.out;
inst.addTransformer(new ClassFileTransformer() {
public byte[] transform(ClassLoader loader, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
String pd = (null == protectionDomain) ? "null" : protectionDomain.getCodeSource().toString();
out.println(className + " loaded by " + loader + " at " + new java.util.Date() + " in " + pd);
// dump stack trace of the thread loading class
Thread.dumpStack();
// we just want the original .class bytes to be loaded!
// we are not instrumenting it...
return null;
}
});
}
}
答案 29 :(得分:0)
我在这条链中的两分钱:
确保类路径包含完整路径(/home/user/lib/some_lib.jar
而不是~/lib/some_lib.jar
),否则您仍会遇到NoClassDefFoundError
错误。
答案 30 :(得分:-1)
我的genymotion设备发生了很多事情。 确保安装了Genymotion的驱动器上有足够的可用内存。