我最近开始学习Java但是我遇到了一些与NoClassDefFoundError
相关的问题。我试图从这个网站和其他地方研究解决方案,但仍然无法解决它们。我使用CLASSPATH环境变量集从Windows 7命令提示符运行我的程序,而不是为每个程序运行定义它。它设置为C:
。为了排除故障,我创建了一个具有简化目录结构的测试包。
在C:\test
,我有Shape.java
和Circle.java
。 Shape.java
看起来像这样:
package test;
class Shape {
void draw() { System.out.println("Drawing a new shape"); }
}
和Circle.java
看起来像这样:
package test;
public class Circle extends Shape {
public static void main(String[] args) {
Circle round = new Circle();
round.draw();
}
}
如果我在命令提示符中使用{/ 1>这样的操作从Shape.java
编译Circle.java
和C:\
C:\>javac test\Shape.java
C:\>javac test\Circle.java
并运行已编译的Circle.class
文件,如
C:\java test\Circle
我得到了我期望的输出:
Drawing a new shape
但是,如果我从Shape.java
内部编译Circle.java
和C:\test
C:\test>javac Shape.java
C:\test>javac Circle.java
然后尝试从
之类的任何位置运行Circle.class
C:\test>java Circle
或者像这样
C:\> java test\Circle
我收到以下错误消息。
Exception in thread "main" java.lang.NoClassDefFoundError: Circle (wrong name: t
est/Circle)
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:792)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:14
2)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:449)
at java.net.URLClassLoader.access$100(URLClassLoader.java:71)
at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
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)
at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:482)
有人可以解释为什么JAVA文件是从C:\test
文件夹中编译的,但编译后的Circle文件会产生错误吗?我的CLASSPATH有问题吗?感谢阅读和希望即将推出的解决方案!
编辑:我做了一些测试,结果证明,如果我从Shape.java
目录编译Circle.java
和C:\test
文件,但是从{{1}运行它目录,它的工作原理。这会改变什么吗?
编辑2:经过更多测试后,事实证明,只要我使用命令java test.Circle,我就可以在C:\ test目录中编译和运行Shape.java和Circle.java文件。我误解了JVM查找类的方式。我现在明白它在分析包导入语句时使用与编译器相同的方法。
答案 0 :(得分:1)
只要你有一个类路径,你就可以在系统的任何地方。
只有这样,java VM才能扫描类路径,并在包test.Circle
中找到类test
。
因此,正确的执行是java test.Circle
(总是),并且类路径需要指向可用\test\Circle.class
的东西。检查Circle.class
是否符合预期。
答案 1 :(得分:0)
您的类路径代表您存储类的位置。因为您已将类路径设置为c:\
。因此,当您使用java
命令启动jvm时,它将从c:\
加载所需的类。当您从C:
编译并运行程序时,您的代码正在运行,因为这些类将被编译并且在这种情况下将出现在C:
中,所以没问题。但是当您从c:\test
编译类时,您的.class文件将出现在c:\ test中,但您的类路径将只加载c:\
而不是c:\test
的类。
答案 2 :(得分:0)
编译,使用
javac -d . Shape.java
javac -d . Circle.java
运行
java test.Circle
-d
用于选择目标目录
.
表示当前目录
因此,在您当前的Directry C:\test\
中,当您编译java文件时,将创建一个名为test
(包名称)的新目录,并且类文件将在其中。
即。C:\test\test\Shape.java
和C:\test\test\Circle.java