我正在使用attach API在运行时加载JVMTI代理。我想在程序完成时卸载JVMTI代理而不终止代理加载的JVM。根据this documentation,无法通过attach API执行此操作。是否有其他方法可以强制代理通过Java API或JVMTI代理程序卸载其自身?
答案 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子类的新实例。 这不是不可能的,但在设计课程重新加载时必须知道。“