我已经尝试了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的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);
}
当运行时类装入器装入的类不能访问已由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;
}
});
}
}
如果您从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