Я знаю, что это было задано и много ответа, но у меня все еще нет хорошего решения, и я до сих пор не понимаю некоторых частей. Поэтому у меня есть требование скомпилировать программные файлы *.java.
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
- это то, что я использую и (как и ожидалось) компилятор null
.
Теперь я знаю, что я должен использовать JDK, а не JRE как "runtime", но вот что-то я не понимаю: недостаточно ли просто поместить tools.jar
в путь к классам приложения и затем получить доступ к API компилятора Java? Если это так, существует (я думаю, есть) разница между автономным Java-приложением и веб-приложениями.
На самом деле, я пытаюсь вызвать JavaCompiler из веб-приложения PlayFramework, поэтому я понял, могут ли эти решения (включая tools.jar
) работать только для автономных приложений?
Я также попытался создать собственный ClassLoader и вызвать вышеупомянутый метод с отражением, но все, что я получаю, это null
для объекта compiler
:
ClassLoader classloader = app.classloader();
File file = new File("lib/tools.jar");
URL url = file.toURI().toURL();
URL[] urls = new URL[]{url};
ClassLoader newCL = new URLClassLoader(urls, classloader) {
};
Class<?> loadClass = newCL.loadClass("javax.tools.ToolProvider");
Method method = loadClass.getMethod("getSystemJavaCompiler", null);
Object object = method.invoke(null);
System.out.println("Object: " + object); // NULL
Объяснение для приведенного выше кода:
- Я просто не использовал try/catch для простоты.
- app.classloader() - это метод воспроизведения, который возвращает ClassLoader приложения
-
tools.jar
включен в мою папку lib в проекте Play (это означает, что он находится в пути к классу проекта - в соответствии с документацией Play)
Я уверен, что перед тем, как Play сможет загрузить класс компилятора Java, я просто не знаю, что мне не хватает.
Мне известны опции, такие как Runtime.exec("javac myFile.java")
и компилятор Eclipse JDT, но это не то, что я ищу.
О, и что-то вроде System.setProperty("java.home", "PATH_TO_YOUR_JDK");
, а затем ToolProvider.getSystemJavaCompiler();
работает, но я считаю это решение таким уродливым.
С наилучшими пожеланиями
EDIT: (чтобы предоставить дополнительную информацию и отобразить последний статус) Это базовое представление структуры web-app:
myApp
|-conf\...
|-lib\MyJar.jar
|-lib\tools.jar
|-logs\...
|-...
В MyJar.jar теперь есть файл META-INF/MANIFEST.MF
со следующим содержимым:
Manifest-Version: 1.0
Sealed: true
Main-Class: here.comes.my.main.class
Class-Path: tools.jar
Без запуска приложения Play я пытаюсь (в папке lib
): java -jar MyJar.jar
- мой простой метод main
пытается вызвать компилятор (ToolProvider.getSystemJavaCompiler();
) и возвращает null
. Таким образом, это заставляет меня поверить, что проблема не имеет ничего общего с Play - я даже не могу получить компилятор при нормальной работе Jar!