使用Class.forName(…)时为什么会出现ClassNotFoundException?

在下面的示例中,我尝试使用sun.tools.javac.Main来动态编译我生成的类,然后实例化该类的对象并调用方法。 到目前为止,我甚至无法通过加载生成的类。 我在Eclipse中遇到以下exception:

 java.lang.ClassNotFoundException: TestHello_1289950330167 at java.net.URLClassLoader$1.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: 

这是代码:

 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(); } } } 

因为它不在类路径中。 将其写入类路径(或将其根路径添加到类路径)或使用URLClassLoader

 File root = new File("."); URLClassLoader classLoader = URLClassLoader.newInstance(new URL[] { root.toURI().toURL() }); Class cls = Class.forName(generatedClassName, true, classLoader); 

java.io使用相对路径是一个坏主意。 您依赖于当前工作目录,该目录在代码中无法控制。

您正在创建一个指向具体文件的新URLClassLoader 。 表达为命令行参数,你这样做:

 java -cp file:///foo/bar/TestHello_1289950330167.java 

然后你的代码调用:

 Class.forName("TestHello_1289950330167",true,cl); 

类路径是JAR文件或文件夹 ,而不是.java文件!

你应该做的是创建一个URLClassLoader,其中包含".".toURI().toURL()作为类路径,而不是javaFileName