Java 为什么在使用 Class.forName(...) 时会出现 ClassNotFoundException?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4200142/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why do I get a ClassNotFoundException when using Class.forName(...)?
提问by Amir Afghani
In the following example, I'm trying to use sun.tools.javac.Main
to dynamically compile a class I generate, then instantiate an object of that class and invoke a method. So far, I can't even get passed loading the generated class. I get the following exception in Eclipse:
在下面的示例中,我尝试使用sun.tools.javac.Main
动态编译我生成的类,然后实例化该类的对象并调用一个方法。到目前为止,我什至无法通过加载生成的类。我在 Eclipse 中收到以下异常:
java.lang.ClassNotFoundException: TestHello_1289950330167
at java.net.URLClassLoader.run(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)
at java.lang.ClassLoader.loadClassInternal(Unknown Source)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Unknown Source)
at MyClassGenerator.runIt(MyClassGenerator.java:47)
at MyClassGenerator.main(MyClassGenerator.java:13)
Note: sun.tools.javac.Main has been deprecated.
1 warning
Running TestHello_1289950330167:
Here's the code:
这是代码:
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileWriter;
import java.net.URL;
import java.net.URLClassLoader;
public class MyClassGenerator {
String generatedClassName = "TestHello_" + System.currentTimeMillis();
String javaFileName = this.generatedClassName + ".java";
public static void main(final String args[]) {
final MyClassGenerator mtc = new MyClassGenerator();
mtc.createIt();
if (mtc.compileIt()) {
System.out.println("Running " + mtc.generatedClassName + ":\n\n");
mtc.runIt();
}
else {
System.out.println(mtc.javaFileName + " is bad.");
}
}
public void loadIt() {
final ClassLoader classLoader = MyClassGenerator.class.getClassLoader();
try {
final Class aClass = classLoader.loadClass(this.generatedClassName);
System.out.println("Loaded " + aClass.getName());
}
catch (final ClassNotFoundException e) {
e.printStackTrace();
}
}
public void createIt() {
try {
final FileWriter aWriter = new FileWriter(this.javaFileName, true);
aWriter.write("public class " + this.generatedClassName + " { }");
aWriter.flush();
aWriter.close();
}
catch (final Exception e) {
e.printStackTrace();
}
}
public boolean compileIt() {
final String[] source = { new String(this.javaFileName) };
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
new sun.tools.javac.Main(baos, source[0]).compile(source);
System.out.print(baos.toString());
return (baos.toString().indexOf("error") == -1);
}
public void runIt() {
try {
final File file = new File(this.javaFileName);
final URLClassLoader classLoader = URLClassLoader.newInstance(new URL[] { file.toURI().toURL() });
final Class<?> cls = Class.forName(this.generatedClassName, true, classLoader);
}
catch (final Exception e) {
e.printStackTrace();
}
}
}
采纳答案by BalusC
Because it's not in the classpath. Either write it to the classpath (or add its root path to the classpath) or use URLClassLoader
.
因为它不在类路径中。将其写入类路径(或将其根路径添加到类路径)或使用URLClassLoader
.
File root = new File(".");
URLClassLoader classLoader = URLClassLoader.newInstance(new URL[] { root.toURI().toURL() });
Class<?> cls = Class.forName(generatedClassName, true, classLoader);
Using relative paths in java.io
is by the way a bad idea. You're dependent on the current working directory which is not controllable from in the code.
java.io
顺便说一下,使用相对路径是一个坏主意。您依赖于代码中无法控制的当前工作目录。
回答by mhaller
You are creating a new URLClassLoader
which points to a concrete file. Expressed as command line arguments, you're doing it like this:
您正在创建一个URLClassLoader
指向具体文件的新文件。表示为命令行参数,你这样做:
java -cp file:///foo/bar/TestHello_1289950330167.java
And then your code calls this:
然后你的代码调用这个:
Class.forName("TestHello_1289950330167",true,cl);
A class path is either a JAR file or a folder, not a .java file!
类路径是 JAR 文件或文件夹,而不是 .java 文件!
What you should do is creating an URLClassLoader with ".".toURI().toURL()
as the class path, not the javaFileName
.
您应该做的是创建一个 URLClassLoader".".toURI().toURL()
作为类路径,而不是javaFileName
.