8

そこで私は最近、JDK1.6で利用可能な新しいJavaCompilerAPIについて知りました。これにより、実行中のコードから直接ファイルにコンパイルStringすることが非常に簡単になります。.class

String className = "Foo";
String sourceCode = "...";

JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();

List<JavaSourceFromString> unitsToCompile = new ArrayList<JavaSourceFromString>() 
    {{ 
         add(new JavaSourceFromString(className, sourceCode)); 
    }};

StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
compiler.getTask(null, fileManager, null, null, null, unitsToCompile).call();
fileManager.close();    

ByteArrayOutputStream bos = new ByteArrayOutputStream();
FileInputStream fis = new FileInputStream(className + ".class");
IOUtils.copyStream(fis, bos);

return bos.toByteArray();

JavadocJavaSourceFromStringからソースを取得できます。

これは、現在の作業ディレクトリに 非常に便利にコンパイルsourceCodeされます。Foo.class

私の質問は:配列に直接コンパイルし、 I / Oをbyte[]処理する煩わしさを完全に回避することは可能ですか?File

4

3 に答える 3

3

たぶん、あなたはあなた自身のjavax.tools.JavaFileManager実装クラスを作成することができ、そこであなたはあなた自身の実装を返し、javax.tools.FileObjectそれをディスクではなくメモリに書き出すでしょう。したがって、javax.tools.FileObject Writer openWriter() throws IOExceptionメソッドのサブクラスに対して、を返しますjava.io.StringWriter。すべてのメソッドをString対応するメソッドに変換する必要があります。

于 2010-01-25T03:47:43.120 に答える
3

バイト配列にバイトコードを書き込むための標準APIがない理由は、単一のJavaソースファイルをコンパイルすると、複数のバイトコードファイルが生成される可能性があるためです。たとえば、ネストされた/内部/匿名のクラスを持つソースファイルは、複数のバイトコードファイルになります。

独自のJavaFileManagerをロールする場合は、この状況に対処する必要があります。

于 2010-01-25T04:45:15.943 に答える
2

JSR 199 APIに同梱されているデモアプリケーションには、メモリ内の文字列からのコンパイルの例がありました(実際にはを使用していますMemoryFileManager)。たぶんここここでそれを見てください(これらのサンプルは少し時代遅れですが、わずかな変更が必要になります)。また、その場でコンパイルする方法を確認してください。Java.netの記事。

PS:私はすべての詳細を見ていませんでしたが、スティーブンCによって言及されたケースを処理するとは思いません。

于 2010-01-25T05:01:34.183 に答える