Укажите путь вывода для динамической компиляции
-
19-09-2019 - |
Вопрос
Моя динамическая компиляция в Java 6 работает отлично.Однако я хотел бы изменить путь вывода.Я перепробовал массу вещей (я пощажу вас), но безрезультатно.В любом случае, вот рабочий код
String[] filesToCompile = { "testFiles/Something.java" };
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjects(filesToCompile);
CompilationTask task = compiler.getTask(null, fileManager, null,null, null, compilationUnits);
System.out.println("Good? " + task.call());
Но выходные данные отправляются в исходный каталог, а это не то, что я хочу.
Я подозреваю, что ответ может заключаться в compiler.getTask
но API не очень четко определяет, что могут означать некоторые параметры.Или, возможно, что-то с FileManager.Я пытался
fileManager.setLocation(StandardLocation.locationFor("testFiles2"), null);
но опять же, гадать, вероятно, не очень хорошая идея.
Спасибо!
Редактировать: Я тоже пробовал использовать опции, подобные этой (извините, если есть более компактный способ):
final List<String> optionsList = new ArrayList<String>();
optionsList.add("-d what");
Iterable<String> options = new Iterable<String>() {
public Iterator<String> iterator() {
return optionsList.iterator();
}
};
а затем передаю параметры в getTask, но появляется сообщение об ошибке "Недопустимый флаг".
Решение
Код в первом сообщении должен был бы работать, но выдается следующая ошибка get:
java.lang.IllegalArgumentException: invalid flag: -d folder
Это происходит потому, что, проходя "-d folder"
заставляет анализатор думать, что он анализирует один вариант.Параметры должны быть разделены следующим образом "-d", "folder"
.
Ниже приведен рабочий пример:
JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager sjfm = javaCompiler.getStandardFileManager(null, null, null);
String[] options = new String[] { "-d", "output" };
File[] javaFiles = new File[] { new File("src/gima/apps/flip/TestClass.java") };
CompilationTask compilationTask = javaCompiler.getTask(null, null, null,
Arrays.asList(options),
null,
sjfm.getJavaFileObjects(javaFiles)
);
compilationTask.call();
Другие советы
Сегодня я столкнулся с той же проблемой.
Ответ ( используя обычный getTask
метод вместо `run ) заключается в указании выходного каталога в FileManager:
fileManager.setLocation(StandardLocation.CLASS_OUTPUT, Arrays.asList(outputDir));
И это все!!:)
Документация немного вводит в заблуждение, я имею в виду, что образец мог бы оказаться очень кстати.Но в конце концов это привело меня туда.
Редактировать
Вот работающий образец:
// write the test class
File sourceFile = new File("First.java");
FileWriter writer = new FileWriter(sourceFile);
writer.write(
"package load.test;\n" +
"public class First{}"
);
writer.close();
// Get the java compiler for this platform
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fileManager = compiler.getStandardFileManager(
null,
null,
null);
//-- H E R E --//
// Specify where to put the genereted .class files
fileManager.setLocation(StandardLocation.CLASS_OUTPUT,
Arrays.asList(new File("/tmp")));
// Compile the file
compiler
.getTask(null,
fileManager,
null,
null,
null,
fileManager.getJavaFileObjectsFromFiles(Arrays.asList(sourceFile)))
.call();
fileManager.close();
// delete the file
sourceFile.deleteOnExit();
У меня 0 опыта работы с инструментами динамического компилятора Java 6.Но больше никто не ответил :)
Задача компиляции получает FileManager
объект.Если вы используете стандартный, то классы генерируются в дереве исходного каталога.Что вы могли бы сделать, это предоставить вашему собственному подклассу FileManager переопределенный getFileForOutput
способ.Описание API getFileForOutput указывает, что это повлияет на то, куда будут отправляться ваши выходные файлы (= class).
Обновить
Как подключить файловые менеджеры
Перенаправление javafilemanager, перенаправление FileObject и перенаправление JavaFileObject Подклассы недоступны для переопределения поведения стандартного файлового менеджера, поскольку он создается путем вызова метода в компиляторе, а не путем вызова конструктора.Вместо этого следует использовать перенаправление (или делегирование).Эти классы упрощают перенаправление большинства вызовов к заданному файловому менеджеру или файловому объекту, позволяя при этом настраивать поведение.Например, рассмотрим, как регистрировать все вызовы в JavaFileManager.flush():
final Logger logger = ...;
Iterable<? extends JavaFileObject> compilationUnits = ...;
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager stdFileManager = compiler.getStandardFileManager(null, null, null);
JavaFileManager fileManager = new ForwardingJavaFileManager(stdFileManager) {
public void flush() {
logger.entering(StandardJavaFileManager.class.getName(), "flush");
super.flush();
logger.exiting(StandardJavaFileManager.class.getName(), "flush");
}
};
compiler.getTask(null, fileManager, null, null, null, compilationUnits).call();
Обновление 2
Я прочитал о динамической компиляции и создал свое собственное приложение для этого.Этот код содержит слишком много церемоний (т.е.это можно было бы упростить) но это работает!
package yar;
import javax.tools.JavaCompiler;
import javax.tools.ToolProvider;
public class DynamicCompiler {
JavaCompiler compiler;
public DynamicCompiler() {
this.compiler = ToolProvider.getSystemJavaCompiler();
if (this.compiler == null) {
throw new NullPointerException("Cannot provide system compiler.");
}
}
public void compile() {
this.compiler.run(null, System.out, System.err,
"-d", "testFiles2",
"testFiles/Hello1.java", "testFiles/Hello2.java");
}
/**
* @param args
*/
public static void main(String[] args) {
try {
DynamicCompiler dc = new DynamicCompiler();
dc.compile();
} catch (Exception e) {
System.err.println(e.getMessage());
}
}
}
Я не уверен, как заставить этот код работать с динамически генерируемым списком файлов Java;Я бы, наверное, просто сделал compiler.run
отдельно для каждого исходного файла.