10

これは尋ねられ、多くの回答がありましたが、私はまだ良い解決策がなく、まだ一部の部分を理解していません。だから私は* .javaファイルをプログラムでコンパイルする必要があります。プログラムでJavaファイルをコンパイルします

JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); 

私が使用しているもの(期待通り)はnullです。 今、私はJREを "ランタイム"として使用する必要はないことを知っていますが、ここでは理解できないことがあります。tools.jarをアプリケーションのクラスパスに入れてJava Compiler APIにアクセスできますか?これが当てはまる場合は、スタンドアロンのJavaアプリケーションとWebベースのアプリケーションの間に違いがあると思います。 実際、私はPlayFramework webappからJavaCompilerを呼び出そうとしていますので、(tools.jarを含む)このソリューションはスタンドアロンアプリケーションでのみ動作するのでしょうか?

私は、カスタムクラスローダを作成し、反射して、上記のメソッドを呼び出すことを試みたが、私は取得していますすべてがcompilerオブジェクトのnullです:

    :上記のコードのための

    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は()プレイプロジェクト(これは、それがプロジェクトのクラスパス上にあることを意味し、私のlibフォルダに含まれているアプリケーション
  • tools.jarのClassLoaderを返すプレイ-方法であり、 )

私はPlayがJavaコンパイラクラスをロードする前に、何か必要なことがあると確信しています。紛失しているものはわかりません。

Runtime.exec("javac myFile.java")のようなオプションとEclipse JDTコンパイラは私には分かっていますが、それは私が探しているものではありません。

ああ、何かSystem.setProperty("java.home", "PATH_TO_YOUR_JDK");、次にToolProvider.getSystemJavaCompiler();のように動作していますが、私はこの解決策がとても醜いと感じています。 (追加情報を提供し、最後のステータスを反映する) これはウェブアプリ-構造の基本的な表現です:

myApp 
|-conf\... 
|-lib\MyJar.jar 
|-lib\tools.jar 
|-logs\... 
|-... 

原因は、Myjar.jarが今持っている

EDIT

敬具次の内容のMETA-INF/MANIFEST.MFファイル:

Manifest-Version: 1.0 
Sealed: true 
Main-Class: here.comes.my.main.class 
Class-Path: tools.jar 

- 私の単純なmainメソッドは、コンパイラ(ToolProvider.getSystemJavaCompiler();)を呼び出しようとしており、nullを返します。は、再生アプリケーションを起動するがなくても、libフォルダにあります。これは、問題はPlayとは何の関係もないと私に信じています。通常、Jarを通常実行しているときにコンパイラを手に入れることさえできません。

答えて

0

それはどのようにJREとそれを実行するために管理しなかったdocumentationTo run the Play framework, you need JDK 6 or later.ことに言いましたか?

とにかく、getSystemJavaCompilerがnullを返した場合は、クラスパスにtools.jarがないか、破損していることを意味します。 Sun/Oracle Javaの場合は、それにcom.sun.tools.javac.api.JavacToolクラスがあることを確認してください。

カスタムクラスローダーを使用する場合は、ToolProviderではなく、ロードする必要があるJavacToolクラスです。 - あなたはあなたのコンパイラを持っています

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

JavaCompilerからdefaultJavaCompilerName = "com.sun.tools.javac.api.JavacTool"

サブクラスそれをして、新しいインスタンスを取得:それは、Java 6でそうする方法を見てみましょう。

+0

'JAVA_HOME'は私のdevマシンに設定され、尋ねられたらJDKのパスを返します。しかし '' java.home ''プロパティを( 'System.getProperty(...) 'を使って)実行しているPlayアプリケーションから取得すると、JREへのパスが返されます。多分それが一つの問題です。しかし、クラスパスに 'tools.jar'があるときに問題はありません。そして、私は 'tools.jar'がクラスパスにあり(Webアプリケーションの実行中にチェックされています)、ファイルが破損していないことを確信しています。私は上記のクラスローディングのものを試してみるつもりです。 – user2229298

+0

私は私のubuntuで遊んだので、私はスカラの動作からJavaコンパイラを問題なく利用することができました。多分セットアップに何か問題がありますか? –

+0

'JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();を試しました。 \t \t \t 'app/Global.java'の' onStart'メソッドからSystem.out.println( "Javaコンパイラ:" + javaCompiler); - 私のアプリケーションのクラスパスに 'tools.jar'を付けて - 「ヌル」 – user2229298

1

Webアプリケーションとスタンドアロンアプリケーションに違いはありません。

webappのクラスパスにtools.jarをパッケージ化しないでください。 Javaのクラスローダーは一般的にボトムアップでしか動作しません。したがって、jdkの一部であるToolProviderは、webappクラスパス内のtools.jarを表示しません(webappクラスパスを見ることはできません)。

解決方法:JDKを使用して、それを指すか、またはtools.jarをJava拡張ディレクトリに配置してください。 ext-dirを上書きするには、-Djava.ext.dirプロパティを好きなディレクトリに設定します。

+0

これは正しいと思います。私は、ツールjarを共通の場所に置くか、jdkを使うことを提案します。 – tgkprog

関連する問題