3

リフレクションを介して、実行するメソッドを決定するために何らかの入力 (URL パスなど) を使用する次のコードがあるとします。

// init
map.put("/users/*", "viewUser");
map.put("/users", "userIndex");

// later
String methodName = map.get(path);
Method m = Handler.class.getMethod(methodName, ...);
m.invoke(handler, ...);

これはリフレクションを使用するため、パフォーマンスを向上させることができます。次のように実行できます。

// init
map.put("/users/*", new Runnable() { public void run() { handler.viewUser(); } });
map.put("/users", new Runnable() { public void run() { handler.userIndex(); } });

// later
Runnable action = map.get(path);
action.run();

しかし、そのようなものをすべて手動で作成するRunnableことには、独自の問題があります。実行時にそれらを生成できますか? したがって、最初の例のように入力マップがあり、2 番目の例のマップを動的に作成します。確かに、それを生成することは文字列を構築するだけの問題ですが、それをコンパイルしてロードすることはどうでしょうか?

注:パフォーマンスの向上が非常に小さいことはわかっていますが、時期尚早の最適化の完璧な例です。したがって、これは学術的な質問です。ランタイムの生成とコードのコンパイルに興味があります。

4

4 に答える 4

4

コードを動的に生成する唯一の方法は、ソース コードを生成してコンパイルするか、バイト コードを生成して実行時にロードすることです。前者にはテンプレート ソリューションがあり、後者にはバイトコード操作ライブラリがあります。実際のケースといくつかのプロファイリングがなければ、どちらが優れているかを本当に言うことはできないと思います. メンテナンスの観点から、利用可能な場合はリフレクションが最適なオプションだと思います。

于 2010-10-31T17:46:56.753 に答える
2

ここにあるコードでこれを達成できると思います。しばらく前にこれを試しましたが、使用していたコードがどこにあるのかわかりませんが、これは同じようです。

基本的には、1.6 Compiler API を使用しますが、ソース ファイルを見つけてクラス ファイルを書き込むには「従来とは異なる」方法を使用CompilerIterable<JavaFileObject>ますJavaFileManager。メモリ内のバイナリ コンパイラ出力。

ClassLoaderコードがコンパイルされたので、メモリ内バイト コードから読み取り、適切な FQCN などを使用してクラスをロードできるカスタムのみが必要です。

そして、幸いなことに、すべての準備ができているようです ;)

于 2011-10-05T11:06:35.953 に答える
1

実際、同じメソッドを何度も呼び出すと、リフレクションエンジンは内部で同様の呼び出しスタブを生成します。Method(何度も再作成するのではなく、同じオブジェクトを使用するだけです。)

于 2011-10-06T10:47:21.780 に答える
0

コードを .java ファイルに書き込んで、それを javac でコンパイルし (方法)、Reflection を使用して Java にロードすることができます。

しかし、トレードオフとして、初期化中に Method オブジェクトを取得することもできます。したがって、リクエストごとに invoke() メソッドを呼び出すだけで済みます。

于 2010-10-31T17:49:04.723 に答える