我已经尝试了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的,但它们具有类似的概念。


当前回答

java.lang.NoClassDefFoundError

指示在编译时找到了一些东西,但在运行时没有找到。也许你只需要把它添加到类路径中。

其他回答

当运行时类装入器装入的类不能访问已由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;
            }
        });
    }
}

在一个NetBeans项目上工作了好几个月之后,在收到“低内存”警报后不久,我突然收到了NoClassDefFoundError消息。进行Clean重建并没有帮助,但是完全关闭NetBeans并重新启动项目时没有出现错误报告。

如果您正在使用Maven,这可能是由于pom.xml中依赖关系的范围(如果它们被设置为“提供”),请尝试将其更改为“编译”。

Java 11 + Eclipse解决方案:

如果您在Eclipse项目中没有使用module-info.java,并且手动添加JAR文件,而不是使用Maven/Gradle,则此解决方案适合您。

右键单击项目→生成路径→配置生成路径→库选项卡 从模块路径中删除有问题的JAR文件 将JAR文件添加到类路径中

更多信息请参阅 在Eclipse中,modulepath和classpath之间的区别是什么?

检查类中是否有静态处理程序。如果是这样,请小心,因为静态处理器只能在有循环程序的线程中启动,崩溃可能会以这种方式触发:

首先,在一个简单的线程中创建类的实例并捕获崩溃。 然后在主线程中调用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);
}