我已经尝试了Oracle的Java教程中的两个示例。它们都可以编译,但在运行时,都会出现这个错误:
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类放入图形包之后(我添加了图形包;对于它),将类路径设置为“_test”(包含图形的文件夹),编译它,并使用Java图形运行它。Main(从命令行),它工作正常。
真的很晚更新#2
我没有使用Eclipse(只有notepad++和JDK),上面的更新解决了我的问题。然而,这些答案中似乎有许多是针对Eclipse和IntelliJ IDEA的,但它们具有类似的概念。
在编译代码之后,程序中的每个类都有.class文件。这些二进制文件是Java解释以执行程序的字节码。NoClassDefFoundError表示负责动态加载类的类加载器(在本例中为java.net.URLClassLoader)无法为您试图使用的类找到.class文件。
Your code wouldn't compile if the required classes weren't present (unless classes are loaded with reflection), so usually this exception means that your classpath doesn't include the required classes. Remember that the classloader (specifically java.net.URLClassLoader) will look for classes in package a.b.c in folder a/b/c/ in each entry in your classpath. NoClassDefFoundError can also indicate that you're missing a transitive dependency of a .jar file that you've compiled against and you're trying to use.
例如,如果你有一个类com.example。Foo,编译后你会有一个类文件Foo。class。例如,您的工作目录是…/project/。那个类文件必须放在…/project/com/example,然后将类路径设置为…/project/。
旁注:我建议充分利用Java和JVM语言的惊人工具。像Eclipse和IntelliJ IDEA这样的现代ide和像Maven或Gradle这样的构建管理工具将帮助您不必担心类路径,而将注意力集中在代码上!也就是说,这个链接解释了在命令行上执行时如何设置类路径。
我想纠正其他人对NoClassDefFoundError的看法。
NoClassDefFoundError的发生有多种原因,比如:
没有为该引用的类找到.class,无论它在编译时是否可用(i. ClassNotFoundException)。E基类/子类)。
类文件已定位,但在初始化静态变量时引发异常
类文件定位,在初始化静态块时引发异常
在最初的问题中,这是第一个可以通过将CLASSPATH设置为引用的类JAR文件或其包文件夹来纠正的情况。
“在编译时可用”是什么意思?
在代码中使用引用的类。例如:两个类,A和B(扩展A)。如果B在代码中直接引用,则在编译时可用,即A A = new B();
“编译时不可用”是什么意思?
编译时类和运行时类是不同的,例如,基类是使用子类的类名加载的
forname(“名称”)
例如:两个类,A和B(扩展A)
A A = Class.forName("B").newInstance();
当在类路径中找不到预期的类时,就会发生无类定义异常。
在编译时类:类是从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已经正确设置)
Go to folder "NoClassDefinationFoundExceptionDemo"
Compile Java source files
javac ClassB
javac ClassA
Both files are compiled successfully and generated class files in the same folder as ClassA.class and ClassB.class
Now since we are overriding ClassPath to the current working director, we execute the following command
java -cp . ClassA
and it worked successfully and you will see the output on the screen
Now let's say, you removed ClassB.class file from the present directory.
And now you execute the command again.
java -cp . ClassA Now it will greet you with NoClassDefFoundException. As ClassB which is a dependency for ClassA is not found in the classpath (i.e., the present working directory).
当运行时类装入器装入的类不能访问已由Java rootloader装入的类时,我得到NoClassFoundError。因为不同的类装入器在不同的安全域中(根据Java), JVM不允许在运行时装入器地址空间中解析已经由rootloader装入的类。
使用'java -javaagent:trace .jar [your 'java' ARGUMENTS]'运行程序
它产生显示已加载类的输出,以及加载该类的加载器环境。追踪类为什么不能解析是非常有用的。
// 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;
}
});
}
}
Java中的NoClassDefFoundError:
定义:
如果一个类在编译时存在,但在运行时java类路径中不可用,则会出现NoClassDefFoundError。通常,当你获得NoClassDefFoundError时,你会在log中看到下面这行:
线程“main”异常
可能的原因:
The class is not available in Java Classpath.
You might be running your program using jar command and class was not defined in manifest file's ClassPath attribute.
Any start-up script is overriding Classpath environment variable.
Because NoClassDefFoundError is a subclass of java.lang.LinkageError it can also come if one of it dependency like native library may not available.
Check for java.lang.ExceptionInInitializerError in your log file. NoClassDefFoundError due to the failure of static initialization is quite common.
If you are working in J2EE environment than the visibility of Class among multiple Classloader can also cause java.lang.NoClassDefFoundError, see examples and scenario section for detailed discussion.
可能的决议:
验证所有必需的Java类都包含在应用程序的类路径中。最常见的错误是,在开始执行依赖于一些外部库的Java应用程序之前,没有包括所有必要的类。
应用程序的类路径是正确的,但是classpath环境变量在应用程序执行之前被重写。
验证前面提到的ExceptionInInitializerError没有出现在应用程序的堆栈跟踪中。
资源:
解决Java J2EE中Java .lang. noclassdeffounderror的3种方法
noclassdeffounderror -如何解决没有类Def发现错误
检查类中是否有静态处理程序。如果是这样,请小心,因为静态处理器只能在有循环程序的线程中启动,崩溃可能会以这种方式触发:
首先,在一个简单的线程中创建类的实例并捕获崩溃。
然后在主线程中调用Class的field方法,你会得到NoClassDefFoundError。
下面是测试代码:
public class MyClass{
private static Handler mHandler = new Handler();
public static int num = 0;
}
在Main活动的onCreate方法中,添加测试代码部分:
@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);
}
如果您从JAR文件“开始”一个类,请确保从JAR完整路径开始。例如,(如果你的“主类”没有在Manifest中指定):
java -classpath "./dialer.jar" com.company.dialer.DialerServer
如果存在任何依赖关系,例如对其他JAR文件的依赖关系,则可以解决此类依赖关系
或者通过将这样的JAR文件(每个JAR文件的完整路径)添加到类路径。例如,
java -classpath "./libs/phone.jar;./libs/anotherlib.jar;./dialer.jar" com.company.dialer.DialerServer
或者通过向清单中添加“依赖JAR无文件”来编辑JAR清单。这样的清单文件可能如下所示:
Manifest-Version: 1.0
Class-Path: phone.jar anotherlib.jar
Build-Jdk-Spec: 1.8
Main-Class: com.company.dialer.DialerServer
或者(如果你是一个有源代码的开发人员),你可以使用Maven为你准备一个清单,添加到*。pom文件:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>com.company.dialer.DialerServer</mainClass>
<!-- Workaround for Maven bug #MJAR-156 (https://jira.codehaus.org/browse/MJAR-156) -->
<useUniqueVersions>false</useUniqueVersions>
</manifest>
</archive>
</configuration>
</plugin>
请注意,上面的例子使用;作为类路径中的分隔符(它对Windows平台有效)。在Linux上,替换;:。
例如,
java -classpath ./libs/phone.jar:./libs/anotherlib.jar:./dialer.jar
com.company.dialer.DialerServer