Почему я получаю ClassNotFoundException при использовании Class.forName (...)? - PullRequest
2 голосов
/ 17 ноября 2010

В следующем примере я пытаюсь использовать sun.tools.javac.Main для динамической компиляции класса, который я генерирую, затем создать экземпляр объекта этого класса и вызвать метод. Пока что я даже не могу передать загрузку сгенерированного класса. Я получаю следующее исключение в Eclipse:

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

Ответы [ 2 ]

6 голосов
/ 17 ноября 2010

Потому что его нет в пути к классам. Либо запишите его в classpath (или добавьте его корневой путь к classpath), либо используйте URLClassLoader.

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

Использование относительных путей в java.io, кстати, плохая идея. Вы зависите от текущего рабочего каталога, который не контролируется в коде.

1 голос
/ 17 ноября 2010

Вы создаете новый URLClassLoader, который указывает на конкретный файл.Выражаясь в качестве аргументов командной строки, вы делаете это так:

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

А затем ваш код вызывает это:

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

Путь к классу - это либо файл JAR, либо папка , а не файл .java!

Вам нужно создать URLClassLoader с ".".toURI().toURL() в качестве пути к классу, а не javaFileName.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...