これについて多くの質問と回答が寄せられていることは知っていますが、まだ適切な解決策がなく、一部の部分を理解していません。そのため、*.java ファイルをプログラムでコンパイルする必要があります。
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
は私が使用しているもので、(予想どおり) コンパイラはnull
. さて、JRE ではなく JDK を「ランタイム」として使用する必要があることはわかっていますが、ここで私が理解できないことがtools.jar
あります。アプリケーションのクラスパスを入力してからアクセスするだけで十分ではないでしょうか。 Java コンパイラ API に? これが本当なら、スタンドアロンの Java アプリケーションと Web ベースのアプリケーションに違いはありますか (あると思います)。実際、私は PlayFramework webapp から JavaCompiler を呼び出そうとしているので、おそらくこのソリューション (を含む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 を返す Play メソッドです。
tools.jar
Playプロジェクトの私のlibフォルダーに含まれています(これは、Playのドキュメントによると、プロジェクトのクラスパス上にあることを意味します)
Play が Java Compiler クラスをロードできるようになる前に、他に何かしなければならないことがあると確信しています。何が欠けているのかわかりません。
や Eclipse JDT コンパイラなどのオプションRuntime.exec("javac myFile.java")
は知っていますが、それは私が探しているものではありません。
ああ、そしてSystem.setProperty("java.home", "PATH_TO_YOUR_JDK");
and thenのようなものToolProvider.getSystemJavaCompiler();
が機能していますが、このソリューションはとても醜いと思います。
よろしくお願いします
EDIT : (追加情報を提供し、最後のステータスを反映するため) これは web-app-structure の基本的な表現です:
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
ます: したがって、これは問題が Play とは何の関係もないことを私に信じ込ませます。通常、Jar を実行しているときにコンパイラを取得することさえできません!main
ToolProvider.getSystemJavaCompiler();
null