12

関連: 実行時にクラスのバイトコードを取得する方法はありますか?

Clojure に耐久性を追加していて、ようやく関数を追加する準備が整いました。Clojure では、関数は (とりわけ) 呼び出しメソッドを持つクラスにバイト コンパイルされます。このように、関数はファースト クラスです。これらを永続的にするには、これらのクラスをシリアライズおよびデシリアライズする必要があります。.class ファイルにアクセスせずにクラスのバイトコードを取得するにはどうすればよいですか?

間違っている場合は訂正してください。ただし、エージェントを使用するには、最初の VM に接続するエージェントで別の VM を生成する必要があります。同じ VM から実行する必要があります。

Serializable を使用して Class オブジェクトを設定および取得するだけでは十分ではありません。デシリアライズ時にクラスをロードする必要があり、後続の VM インスタンスでクラス名の競合が発生する可能性があります。逆シリアル化/クラスの読み込み時にクラスの名前を一意に変更するには、バイトコードを変更する必要があります。

4

3 に答える 3

5

ClassLoaderクラスがロードされるときにバイトコードを記録するスキームを独自に作成してハックすることができます。

findClassクラスファイルを自分で見つけてメモリにロードし、データをどこかに保存して(後でシリアル化するために)オーバーライドしdefineClassて、JVMでそのクラスを定義するために呼び出す必要があります。

于 2010-11-09T06:39:35.530 に答える
3

トリッキーなクラスローダーを介してコードを実行していない限り、次のようなことができるはずです。

Class<?> clazz = ....
String className = clazz.getCanonicalName();  // e.g. "foo.Bar"
String resourceName = ... // map className to a resource name; e.g. "/foo/Bar.class" 
InputStream is = clazz.getClassLoader().getResourceAsStream(resourceName);

これにより、「.class」ファイルの内容のハンドルが得られます...見つかった場合。

警告。一部のクラスローダーは次の可能性があります。

  • 「.class」リソースをまったく開かないようにします。
  • 暗号化されたバイトコード ストリームを提供する、または
  • クラスローダによってオンザフライで変換が実行されるため、実行されているものとはまったく異なるバイトコードが返されます。

このアプローチが機能しない場合、JVM はロードされた実際のバイトコードにアクセスする方法を提供しないため、ほとんど選択肢がありません。

于 2010-11-09T06:30:57.980 に答える
1

これには Java Instrumentation API を使用することもできます。defineClass が呼び出される前に、クラスファイルのバイトにアクセスできます。あなたもそれらを変更することができます!

于 2012-07-20T19:23:29.433 に答える