であるクラスを注入しようとしたとき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ためのオープンチケットは、それが解決されるまで、これは一般的な回避策です。