【发布时间】:2012-11-10 10:16:25
【问题描述】:
我是一个经验丰富的程序设计人员,我遇到了一个非常奇怪的问题,到目前为止我还无法解决。我收到此错误:
Exception in thread "Thread-0" java.lang.NoClassDefFoundError: rec/MiscIO
at rec.RECTool.run(RECTool.java:264)
at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.ClassNotFoundException: rec.MiscIO
at java.net.URLClassLoaderrun(Unknown Source)
at java.net.URLClassLoaderrun(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
... 2 more
这是相关的行:
File savedTo = MiscIO.copyJar(root);
我不明白的是,这是一个小应用程序,并且使用的类在同一个包中。除了类名和内容外,基本相同。但是,我只在我的一些课程中特别得到了错误,而不是全部。我在错误发生之前使用这些行,它们在同一个包中。
Logger.log("Found new root: " + newRoots[i0]);
...
FileLocker locker = new FileLocker();
...
locker.lock(PathManager.getJar());
所以三个类的设置与出错的一个基本相同,只有一个抛出异常。这对我来说毫无意义。
我尝试了各种参数来运行 jar,包括修改类路径和直接调用主类而不是使用 jar 命令,但无济于事,例如:
java -jar <jarname>
java -cp . <jarname>
java -cp <jarname> -jar <jarname>
java -cp <jarname> <main class here>
但是,如果我解压缩 jar 并运行程序,则不会发生错误。我认为这可能是 MiscIO 无法加载或静态初始化程序无法加载的某种依赖关系,但我的代码中都没有。
另外,我正在使用 Netbeans 生成 jar,并且清单设置正确。这是完整的代码:
package rec;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.net.URL;
/**
* @author Colby
*/
public class MiscIO {
public static void copyJar(RandomAccessFile out) throws IOException {
URL jarSource = RECTool.class.getProtectionDomain().getCodeSource().getLocation();
InputStream in = null;
try {
in = jarSource.openStream();
copyToRAF(in, out);
} finally {
if (in != null) {
in.close();
}
}
}
public static File copyJar(File saveJarTo) throws IOException {
URL jarSource = RECTool.class.getProtectionDomain().getCodeSource().getLocation();
saveJarTo = new File(saveJarTo, "classlist.jar");
InputStream in = null;
OutputStream out = null;
try {
in = jarSource.openStream();
out = new FileOutputStream(saveJarTo);
copyStream(in, out);
} finally {
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
}
return saveJarTo;
}
public static void copyStream(InputStream in, OutputStream out) throws IOException {
int len;
byte[] data = new byte[1024 * 8];
while ((len = in.read(data)) != -1) {
out.write(data, 0, len);
}
out.flush();
}
public static void copyToRAF(InputStream in, RandomAccessFile raf) throws IOException {
raf.seek(0L);
int len;
byte[] data = new byte[1024 * 8];
while ((len = in.read(data)) != -1) {
raf.write(data, 0, len);
}
}
public static void copyFile(File from, File to) throws IOException {
FileInputStream in = null;
FileOutputStream out = null;
try {
in = new FileInputStream(from);
out = new FileOutputStream(to);
copyStream(in, out);
} finally {
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
}
}
}
最后一点,我认为这可能是我的机器上安装的 Java 版本冲突,或者偶然发生的 x86/x64 冲突,所以我卸载了所有 Java 发行版,只安装了一个架构中的最新版本,问题仍然存在。 你们有谁以前见过这样的事情吗?
【问题讨论】:
-
NoClassDefFoundError:如果 Java 虚拟机或 ClassLoader 实例尝试加载类的定义(作为正常方法调用的一部分或使用新表达式)并且无法构造该类的有效表示。
-
报错说明问题出在RECTool.java:264。贴出相应的 RECTool.java 代码,看看你是如何调用 MiscIO 类的。
-
(也就是说异常并不意味着找不到类。事实上,类很可能被找到了,但是有些东西阻止了它被使用,通常是JAR文件不匹配,但偶尔会在静态初始化期间出现错误或类似情况。通常在异常跟踪中会有一个较早的异常提示特定原因。)
-
这有点像类加载器问题,您在不同的类加载器下加载了相同的类。
-
(虽然考虑到斯蒂芬的回答,但很可能您只是将类放在 jar 中的错误位置——不是在目录“rec”中,而是在根目录中。)