在运行时卸载JVMTI代理?

时间:2011-05-25 13:00:12

标签: java jvmti

我正在使用attach API在运行时加载JVMTI代理。我想在程序完成时卸载JVMTI代理而不终止代理加载的JVM。根据this documentation,无法通过attach API执行此操作。是否有其他方法可以强制代理通过Java API或JVMTI代理程序卸载其自身?

2 个答案:

答案 0 :(得分:6)

JVMTI spec says卸载(没有JVM终止)是可能的,但是依赖于平台且超出了规范的范围。

答案 1 :(得分:0)

您必须以编程方式加载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();

请参阅doc here

之后,您必须使用与默认值不同的classLoad:

您必须将系统属性“java.system.class.loader”设置为目标JVM的自定义类加载器的名称。

请参阅doc here

“Java的内置类加载器总是在加载之前检查类是否已经加载。 因此,使用Java的内置类加载器无法重新加载类。 要重新加载类,您必须实现自己的ClassLoader子类。“

在您的情况下,您必须实现一个ClassLoader,其ClassLoader.getSystemClassLoader()具有父级。

“即使使用ClassLoader的自定义子类,您也面临挑战。 每个加载的类都需要链接。 这是使用ClassLoader.resolve()方法完成的。 此方法是最终的,因此无法在ClassLoader子类中重写。 resolve()方法不允许任何给定的ClassLoader实例两次链接同一个类。 因此,每次要重新加载类时,都必须使用ClassLoader子类的新实例。 这不是不可能的,但在设计课程重新加载时必须知道。“

请参阅Dynamic Class Reloading