在运行时卸载 JVMTI 代理?

发布于 2024-11-09 22:40:51 字数 270 浏览 2 评论 0原文

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

I'm using the attach API to load a JVMTI agent at runtime. I'd like to unload the JVMTI agent when my program is done without terminating the JVM the agent is loaded in. According to this documentation there is no way to do this from the attach API. Are there any other ways to force an agent to unload its self either through a Java API or from within the JVMTI agent?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

Spring初心 2024-11-16 22:40:51

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

JVMTI spec says unloading (without JVM termination) is possible, but platform-dependent and out of specification's scope.

简单 2024-11-16 22:40:51

您必须以编程方式加载 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 的加载程序。

请参阅此处的文档

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

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

“即使使用 ClassLoader 的自定义子类,您也会遇到挑战。
每个加载的类都需要链接。
这是使用 ClassLoader.resolve() 方法完成的。
此方法是最终方法,因此不能在 ClassLoader 子类中重写。
solve() 方法不允许任何给定的 ClassLoader 实例链接同一个类两次。
因此,每次要重新加载类时,都必须使用 ClassLoader 子类的新实例。
这并非不可能,但在设计类重新加载时有必要了解。”

请参阅 动态类重新加载

You have to load JVMTI agent programatically :

// 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();

see doc here

After that you have to use a different classLoad than default :

You have to set the system property "java.system.class.loader" to be the name of your custom class loader for your target JVM.

see doc here

"Java's builtin Class loaders always checks if a class is already loaded before loading it.
Reloading the class is therefore not possible using Java's builtin class loaders.
To reload a class you will have to implement your own ClassLoader subclass."

In your case you have to implement a ClassLoader which has ClassLoader.getSystemClassLoader() has parent.

"Even with a custom subclass of ClassLoader you have a challenge.
Every loaded class needs to be linked.
This is done using the ClassLoader.resolve() method.
This method is final, and thus cannot be overridden in your ClassLoader subclass.
The resolve() method will not allow any given ClassLoader instance to link the same class twice.
Therefore, everytime you want to reload a class you must use a new instance of your ClassLoader subclass.
This is not impossible, but necessary to know when designing for class reloading."

see Dynamic Class Reloading

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文