18

Java 5 および Java 6 で (メモリ内の) 任意の文字列から Java コードをコンパイルし、それをロードして、(事前定義された) 特定のメソッドを実行するにはどうすればよいですか?

これを炎上させる前に、既存の実装を調べました。

  • ほとんどは Java 6 Compiler API に依存しています。
  • そうでないものは、トリックに依存します。
  • はい、commons-jci を確認しました。それがどのように機能するかを理解するには密度が高すぎるか、単に理解していないかのどちらかです。
  • 現在のクラスパスをコンパイラに供給する方法が見つかりませんでした (これは非常に巨大です)。
  • (Java 6 で) 機能した実装では、内部クラス (または内部匿名クラス) を正しくロードする方法が見つかりませんでした。
  • 複数の環境で実行されるため、全体がメモリ内にあると非常に気に入っています。

これは以前に解決されたと確信していますが、Googleで半製品の品質でさえ見えるものを見つけることができません(前に言ったように、私は使用できなかったjciを除いて)。

編集:

  • 私は JavaAssist を調べました - 内部クラス、Java 5.0 言語レベルのサポート、およびクラスパス全体でのコンパイルが必要です。また、その場で新しいクラスを作成したいと思います。私は間違っているかもしれませんが、JavaAssit でこれを行う方法が見つかりませんでした。
  • ファイルシステムベースのソリューション(javacを呼び出す)を使用したいと思っていますが、クラスパスを推測する方法も、後でファイル(クラスパスにない)を特別なクラスローダーでロードする方法もわかりません。複数の呼び出しのためにリサイクルされます。私はそれを調査する方法を知っていますが、私は準備ができている解決策を好みます.

Edit2: 今のところ、BeanShell の「評価」に満足しています。どうやら、必要なことはすべて実行します (文字列を取得し、「現在の」クラスパスのコンテキストで評価します。Java 5 機能の一部が欠けていますが、列挙型 (定義ではなく) とコンパイル済みの「ジェネリック」 (消去された) を使用できます)。 )クラスなので、私が望むものには十分なはずです。

より良い解決策が出てくることを望んでいるので、まだ回答を承認済みとしてマークしたくありません。

Edit3: beanshell の提案を受け入れました - 本当に素晴らしく動作します。

4

6 に答える 6

10

JCIは問題ないようです。このコード スニペットをベースにする必要があります。

JavaCompiler compiler = new JavaCompilerFactory().createCompiler("eclipse");

MemoryResourceReader mrr = new MemoryResourceReader();
mrr.add("resource name string", yourJavaSourceString.getBytes());

MemoryResourceStore mrs = new MemoryResourceStore();

CompilationResult result = compiler.compile(sources, mrr, mrs);

// don't need the result, unless you care for errors/warnings
// the class should have been compiled to your destination dir

これが機能しない理由はありますか?


編集:MemoryResourceStore要求されたように、コンパイルされたクラス出力をメモリに送信するa を追加しました。

また、あなたの場合のクラスパスのような設定は、クラス内javacで行うことができます。setCustomArguments(String[] pCustomArguments)JavacJavaCompilerSettings

于 2009-03-05T20:52:57.690 に答える
8

Janinoもチェックしてみてください。

彼らのウェブサイトから:

Janino は、JavaTM 式、ブロック、クラス本体、ソース ファイル、またはソース ファイルのセットを読み取り、ロードして直接実行される JavaTM バイトコードを生成するコンパイラです。Janino は開発ツールではなく、式エバリュエーターや JSP などの「サーバー ページ」エンジンなど、ランタイム コンパイル用の組み込みコンパイラです。

http://www.janino.net/

現在、かなり大規模なミッションクリティカルなプロジェクトで使用していますが、問題なく動作します

于 2009-03-05T21:32:06.270 に答える
1

Javassistはあなたに興味があるかもしれません

于 2009-03-05T20:49:50.507 に答える
0

ECJ Eclipse Java コンパイラ

Eclipse は、javac ではない独自のコンパイラーを提供および使用します。

  • Eclipse コンパイラーは IDE (Eclipse) 内で使用されます。
  • Eclipse コンパイラーは、Eclipse 以外の純粋なバッチ コンパイラーとしても使用できます。

ソースファイルをコンパイルする

$ java -jar ecj-3.5.2.jar HelloWorld.java

于 2013-12-13T18:04:51.673 に答える
0

Tomcat のような Web コンテナー内で実行し、最初に JSP ページを生成してから呼び出します。

また、これにより、クラスローダがゆっくりといっぱいになるのではなく、JSP ページを上書きするだけで、古いクラス定義を取り除くことができます。

「メモリ内」の要件は速度のためですか、それともコード ベースを変更しないためですか?

于 2009-03-05T21:39:35.927 に答える