10

Я знаю, что это было задано и много ответа, но у меня все еще нет хорошего решения, и я до сих пор не понимаю некоторых частей. Поэтому у меня есть требование скомпилировать * .java файлы программно.Программно скомпилировать 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 

Объяснение для кода выше:

  • Я не включил попытку/уловы ради простоты.
  • app.classloader() является Плей-метод, который возвращает ClassLoader в App
  • tools.jar входит в мою Lib папку проекта Play (это означает, что он находится на пути к классам проекта - согласно документации Play)

Я уверен, что перед тем,

Параметры, подобные Runtime.exec("javac myFile.java") и компилятор Eclipse JDT, известны мне, но это не то, что я ищу.

О, и что-то вроде System.setProperty("java.home", "PATH_TO_YOUR_JDK");, а затем ToolProvider.getSystemJavaCompiler(); работает, но я нахожу это решение таким уродливым.

С наилучшими пожеланиями

EDIT: (для получения дополнительной информации и отражает последнее состояние) Это базовое представление веб-приложения-структуры:

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!

ответ

0

В сообщении documentation указано, что To run the Play framework, you need JDK 6 or later. Как вам удалось запустить его с помощью jre?

В любом случае, если getSystemJavaCompiler возвращает null, это означает, что у вас нет tools.jar в вашем пути к классу или он поврежден. Если это Java/Java, убедитесь, что в нем есть класс com.sun.tools.javac.api.JavacTool.

И если вы хотите использовать пользовательский загрузчик классов, вам необходимо загрузить класс JavacTool, а не ToolProvider. Посмотрите на то, как он делает это в Java 6:

 URL[] urls = {file.toURI().toURL()}; 
     ClassLoader cl = URLClassLoader.newInstance(urls); 
     cl.setPackageAssertionStatus("com.sun.tools.javac", true); 
     return Class.forName(defaultJavaCompilerName, false, cl); 

где defaultJavaCompilerName = "com.sun.tools.javac.api.JavacTool"

Подкласс, чтобы это JavaCompiler и получить новый экземпляр - вы будете иметь свой компилятор.

+0

'JAVA_HOME' установлен на моей машине dev, возвращая путь к JDK по запросу. Но получение свойства '' java.home'' из запущенного приложения Play (с 'System.getProperty (...)') возвращает путь к JRE. Так что, возможно, это единственная проблема. Но не должно быть проблем, когда у меня есть 'tools.jar' в моем пути к классам. И я уверен, что 'tools.jar' находится в моем пути к классам (проверял его во время запуска веб-приложения) и что файл не поврежден. Я собираюсь попробовать вышеупомянутый материал для загрузки. – user2229298

+0

Я запустил игру на своем ubuntu, и я смог получить java-компилятор из scala-action без каких-либо проблем. Может быть, что-то не так с вашей настройкой? –

+0

Просто попробовал 'JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler(); \t \t \t System.out.println ("Java-компилятор:" + javaCompiler); 'из метода' onStart' в 'app/Global.java' - с' tools.jar' в пути к классам моего приложения - даже это возвращается 'null' – user2229298

1

Разница между веб-приложениями и отдельными приложениями отсутствует.

Вы не должны упаковывать tools.jar в свой путь к классу webapp. Классный загрузчик на Java обычно работает только снизу вверх. Таким образом, ToolProvider, который является частью jdk, не увидит ваши tools.jar в пути к классу webapp (он не может смотреть вниз в путь класса webapp).

Решение: используйте JDK и убедитесь, что вы указали на него или поместите tools.jar в каталог Java ext. Вы можете переопределить внешний каталог, установив свойство -Djava.ext.dir в любой каталог, который вам нравится.

+0

это звучит правильно. я бы предложил положить банку инструментов в обычное место или использовать jdk. – tgkprog

Смежные вопросы