2013-07-15 68 views
1

我最近开始学习Java,但是我遇到了一些与NoClassDefFoundError有关的问题。我试图从这个网站和其他地方研究解决方案,但仍然无法解决它们。我使用CLASSPATH环境变量集从Windows 7命令提示符运行我的程序,而不是为每个程序运行定义它。它设置为C:。为了排除故障,我创建了一个简化目录结构的测试包。带继承类的Java NoClassDefFoundError

C:\test,我有Shape.javaCircle.javaShape.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(); 
    } 
} 

如果我在与操作命令提示符像

C:\>javac test\Shape.java 
C:\>javac test\Circle.java 

和编译都Shape.javaCircle.javaC:\运行编译的Circle.class文件,如

C:\java test\Circle 

我得到的输出我想到:

Drawing a new shape 

但是,如果我编译从C:\test

C:\test>javac Shape.java 
C:\test>javac Circle.java 

Shape.javaCircle.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文件夹中编译,但编译后的文件圈产生错误?我的CLASSPATH有问题吗?感谢您的阅读和希望即将到来的解决方案!

编辑:我做更多的测试,事实证明,如果我编译从C:\test目录Shape.javaCircle.java文件,但是从C:\目录中运行它,它的工作原理。这会改变什么吗?

编辑2:经过更多的测试后,事实证明,我可以事实上编译并运行C:\ test目录下的Shape.java和Circle.java文件,只要我使用命令java test.Circle 。我误解了JVM寻找类的方式。我现在明白它在分析包导入语句时使用与编译器相同的方法。

+0

使用eclipse工作台。 – Makky

+0

使用'java test.Circle' –

+0

您应该认真使用像Eclipse这样的IDE。 –

回答

1

只要你有一个类路径,你可以在系统的任何地方。

只有这样,java VM才能够扫描类路径,并找到包test中的类test.Circle

所以,正确的执行是java test.Circle(总是),并且类路径需要指向可能有\test\Circle.class的东西。检查Circle.class是否您期望它。

+0

+1 - 要确定(基本上你正确地描述了它):类路径需要指向本身包含'test'目录(=包)的目录 - 例如如果'test.Circle'类位于'c:\ bin \ test \ Circle.class'中,那么类路径需要指向'c:\ bin' –

+0

非常感谢这样的快速回复!我的Shape.class和Circle.class文件都在C:\ test目录中创建。 classpath是什么意思?如果我的类路径设置为C:\,并且test \ Circle.class可用,那么编译和运行Circle.class文件的目录是否会有所不同? – user2582713

+0

我的意思是绑定c-kolon-backslash,但我认为编辑器省略了我的击键:)无论如何,正如Andreas所阐明的那样,classpath是搜索树根的集合。无论它是在目录内,在zip文件(或jar文件)中,还是从网络url中。这是类加载器'魔术' –

0

您的类路径代表您存储类的位置。因为您已将类路径设置为c:\。因此,当您使用java命令启动jvm时,它将加载所需的类形式c:\。当你编译并运行程序C:时,你的代码正在工作,因为这些类将被编译,并且在那种情况下将出现在C:中,所以没有问题。但是当你从c:\test编译你的类时,你的.class文件将出现在c:\ test中,但是你的类路径只会加载类c:\而不是c:\test

+0

非常感谢您的回复。这是否意味着,作为一般规则,我应该只从类路径目录编译和运行我的程序? – user2582713

+0

您需要将编译好的类与适当的包结构放在类路径中。或者,您可以随时将当前目录添加到类路径中。一旦你在classpath中拥有你的类,那么你可以从任何地方运行它。 –

+0

但是正在C:\ test目录中生成Shape.class和Circle.class文件。这是不正确的包装结构? – user2582713

0

编译,使用

javac -d . Shape.java 
javac -d . Circle.java 

运行

java test.Circle 

-d是选择目标目录
.意味着当前目录 因此,在当前的直供C:\test\当您编译, java文件,将创建一个名为test(包名称)的新目录,并在其中包含类文件。 即。
C:\test\test\Shape.javaC:\test\test\Circle.java

+0

它工作!你能解释为什么当我从C:\ test目录内编译Shape.java和Circle.java文件时,编译器不会自动创建C:\ test \ test目录吗? – user2582713

+0

@ user2582713如果有效,您可以通过点击我答案左侧的勾号来接受答案。您的评论的答案很明显,我们希望在当前目录中生成类文件,但我不能给你确切的解释。如果你愿意的话,你可以把它作为一个新问题。 –

+0

-d。是默认值。真正的意义在于从包结构的头部进行编译,而不是源文件所在的目录。 – EJP