実行時にJVMTIエージェントをロードするためにアタッチAPIを使用しています。エージェントがロードされているJVMを終了せずにプログラムが完了したら、JVMTIエージェントをアンロードしたいと思います。このドキュメントによると、アタッチAPIからこれを行う方法はありません。Java APIを介して、またはJVMTIエージェント内からエージェントに自身をアンロードさせる他の方法はありますか?
2 に答える
JVMTI仕様では、アンロード(JVM終了なし)は可能であるとされていますが、プラットフォームに依存し、仕様の範囲外です。
プログラムでJVMTIエージェントをロードする必要があります。
// attach to target VM
VirtualMachine vm = VirtualMachine.attach("2177");
// get system properties in target VM
Properties props = vm.getSystemProperties();
// construct path to management agent
String home = props.getProperty("java.home");
String agent = home + File.separator + "lib" + File.separator
+ "your-agent-example.jar";
// load agent into target VM
vm.loadAgent(agent, "com.sun.management.jmxremote.port=5000");
// detach
vm.detach();
その後、デフォルトとは異なるclassLoadを使用する必要があります。
システムプロパティ「java.system.class.loader」を、ターゲットJVMのカスタムクラスローダーの名前に設定する必要があります。
「Javaの組み込みクラスローダーは、クラスをロードする前に、クラスがすでにロードされているかどうかを常にチェックします。したがって、Javaの組み込みクラスローダーを使用してクラスを再ロードすることはできません。クラスを再ロードするには、独自のClassLoaderサブクラスを実装する必要があります。」
あなたの場合、ClassLoader.getSystemClassLoader()が親を持つClassLoaderを実装する必要があります。
「ClassLoaderのカスタムサブクラスでも課題があります。ロードされたすべてのクラスをリンクする必要があります。これはClassLoader.resolve()メソッドを使用して行われます。このメソッドは最終的なものであるため、ClassLoaderサブクラスでオーバーライドすることはできません。解決()メソッドでは、特定のClassLoaderインスタンスが同じクラスを2回リンクすることはできません。したがって、クラスをリロードするたびに、ClassLoaderサブクラスの新しいインスタンスを使用する必要があります。これは不可能ではありませんが、クラスを設計するときに知っておく必要があります。リロードします。」
動的クラスのリロードを参照してください