Скомпилировал класс, но где это? - PullRequest
1 голос
/ 16 октября 2011

Я не специалист по Java, и я довольно новичок во всей концепции компиляции и запуска динамически сгенерированного кода, которая так проста в других языках, особенно в языках сценариев, таких как Javascript и PHP.

Я слежу за этим фрагментом кода: http://www.java2s.com/Code/Java/JDK-6/CompilingfromMemory.htm, и я сделал что-то вроде этого:

private final String = "GeneratedClass_" + Long.toHexString(random.nextLong());
private Method compileCode(String code) {
    JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
    if (compiler == null) return null;

    DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>();

    JavaFileObject source = new JavaSource(className, code);
    Iterable<? extends JavaFileObject> compilationUnits = Arrays.asList(source);
    CompilationTask task = compiler.getTask(null, null, diagnostics, null, null, compilationUnits);

    if (!task.call()) return null;
    try {
        return Class.forName(className).getDeclaredMethods()[0];
    } catch (ClassNotFoundException e) {}
    return null;
}

private class JavaSource extends SimpleJavaFileObject {
    final String code;
    JavaSource(String name, String code) {
        super(URI.create("string:///" + name.replace('.','/') + Kind.SOURCE.extension),Kind.SOURCE);
        this.code = code;
    }

    @Override
    public CharSequence getCharContent(boolean ignoreEncodingErrors) {return code;}
}

Просто представьте, что строковый код - это что-то вроде

"public class GeneratedClass_65ce701239c32ce0 {
    public String hello() {
        return "Hello, world!";
    }
}"

Это работает хорошо до того Class.forName, который выбрасывает ClassNotFoundException.Я озадачен, потому что не похоже, что я вырезал что-то важное из фрагмента: так, класс был скомпилирован, но куда он девался?

Я читал кое-что об использовании другого загрузчика классов, но так какЯ сказал, что я довольно новичок во всем этом, я не знаю, куда идти и как его использовать, и как мне определить свое собственное расширение ClassLoader.Единственное, что я знаю, это то, что мне все кажется довольно сложным ...

Использование Eclipse Indigo в Windows 7 и JDK 1.7.

1 Ответ

2 голосов
/ 16 октября 2011

Одна важная вещь, которую вы вырезали, была вся информация об ошибках и диагностическая информация Вы никогда бы не узнали, если что-то пошло не так. Однако все выглядит правильно. Скорее всего, ваша проблема в том, что вы не отправили какие-либо параметры компилятору, поэтому он запишет файл класса в любое удобное для него место (я считаю, что текущая рабочая папка используется по умолчанию), и это, вероятно, не в вашей classpath, особенно в IDE. Попробуйте запустить его из командной строки, чтобы доказать себе, что это работает. Это должно работать:

mkdir tmp
javac -d tmp <path your main class .java file>
java -cp .;tmp <your main class name>

Если вы не знакомы с инструментами командной строки, аргумент javac должен быть путем файловой системы к файлу .java, а аргумент java должен быть.-Разделенным, полное имя класса, например com.foo.Main. Делать это следует:

  1. Скомпилируйте ваш класс в каталог tmp.
  2. Запишите динамически сгенерированный класс в текущий каталог.
  3. Успешно загрузить вновь скомпилированный класс из текущего каталога, поскольку он находится в пути к классам.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...