java.langのパッケージにクラスを注入する方法

フェリックス:

であるクラスを注入しようとしたときjava.langを経て、名前空間java.lang.instrument.Instrumentation#appendToBootstrapClassLoaderSearch のOpenJDK 11上に、何も起こらないとエラーがスローされません。異なるパッケージに注入するためにクラスを配置する場合は、予想通り、それは動作します。

JarFile jar = new JarFile(new File("file/to/bootstrap.jar));
instrumentation.appendToBootstrapClassLoaderSearch(jar);
// throws ClassNotFoundException java/lang/Dispatcher
Class.forName("java.lang.Dispatcher", false, null);
bootstrap.jar
 └─ java/lang/Dispatcher.class

私はこれをしたい理由は、いくつかのOSGiコンテナの問題を克服することです。彼らは一般的にのみ、特定のパッケージにブートストラップクラスローダに委任を制限します。明らかに常に含まれていることをデフォルトではjava.*、私は私の配置する理由であるDispatcherが、クラスを。私は承知しているのorg.osgi.framework.bootdelegationが、そのプロパティは初期化時に読んで取得します。手段は、実行時にエージェントを取り付けるときに、それはこの値を上書きするために既に手遅れです。

代替は、エージェントクラスの機器すべての既知のOSGiクラスローダへとホワイトリストになります。しかし、バージョンごとに以下実現可能と思われることを各フレームワークとテストのためにそれをやって。

どのように私のようなカスタムクラスを注入することができjava.lang.Dispatcher、ブートストラップクラスローダに?OSGi bootdelegationの問題を回避するためにそこに他のパターンやベストプラクティスはありますか?

いくつかのより多くのコンテキストを提供します:

私の考えではこれだけ注入することであるDispatcherブートストラップクラスローダにクラス。ディスパッチャは、基本的には静的な地図を保持しています。エージェントのクラスの残りの部分はブートストラップクラスローダの子である、専用のURLClassLoaderによってロードされるだろう。エージェントは、登録しますMethodHandle注入されたバイトコードは、エージェントのクラスローダにロードされたエージェントのクラスにアクセスする有効MethodHandlesのネタを得ることができるようにディスパッチャの地図で秒。

ラファエル・ヴィン:

それは危険なAPIを使用することにより可能です。Javaの9以来、ブートクラスローダの実装では、唯一知られているパッケージの指定jmodを確認するには変わっていませんが、ブートの検索パスは、もうチェックされています。

Javaの11も削除sun.misc.Unsafe#defineClass方法が、同じ方法では、まだ入手可能ですjdk.internal.misc.Unsafe

あなたは内部にあるそのクラスのモジュールを開く必要があります。あなたはどちらか使用して行うことができsun.misc.Unsafeますが、フィールドの値を(書くことを可能にするaccessibleアクセシビリティチェックなしまたは計装の公式APIを使用することによって)。

あなたがバイトバディを使用している場合は、見ていClassInjectorすべての実装を提供する実装が近づきました。

あるヘルパークラスを注入するためのJavaエージェントの必要性をadressingためのオープンチケットは、それが解決されるまで、これは一般的な回避策です。

おすすめ

転載: http://43.154.161.224:23101/article/api/json?id=278774&siteId=1