我创建了一个 java 代理 jar 文件(在命令行上完美运行)。接下来,我想将此代理连接到 j2ee 服务器中正在运行的 JVM。所以我使用了代码:
public static void loadAgent() {
System.out.println("dynamically loading javaagent");
String nameOfRunningVM = ManagementFactory.getRuntimeMXBean().getName();
int p = nameOfRunningVM.indexOf('@');
String pid = nameOfRunningVM.substring(0, p);
try {
VirtualMachine vm = VirtualMachine.attach(pid);
String jarFilePath = vm.getSystemProperties().getProperty("java.home")+File.separator+"lib"+File.separator+"test-agent-7.jar";
vm.loadAgent(jarFilePath, "");
vm.detach();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
编辑:现在可以工作了,我可以看到Transformer被调用了。我还可以移除变压器,并能够调试变压器。
我的问题是:
嗯,有几件事需要考虑:
如果你加载代理,你就加载类。只要相关的类加载器在JavaVM的内存中,相关的类就会保持加载状态。我不认为你能轻易地阻止/规避。但是这应该只是你通过加载代理而增加的一小部分内存开销。
一些研究表明,代理将由SystemClassLoader加载,因此卸载这些类是不可能的。
VM启动后的启动代理
实现可以提供一种机制,在VM启动后的某个时间启动代理程序。有关如何启动代理程序的详细信息是特定于实现的,但通常应用程序已经启动,并且其主方法已经被调用。如果实现支持在VM启动后启动代理程序,则应用以下内容:代理程序JAR的清单必须包含属性代理程序类。此属性的值是代理程序类的名称。代理程序类必须实现公共静态代理程序主方法。系统类加载器(ClassLoader.getSystemClassLoader)必须支持将代理程序JAR文件添加到系统类路径的机制。链接到源代码
但是,您可以影响的是代理正在做什么。
您想关闭该代理?提供关闭方法。
如果您想从外部停止代理,这个代理可以提供一个JMXBean来关闭代理。
然后,该方法可以从插装接口中移除转换器,或者停止代理在Java VM中正在做的任何事情(释放被占用的引用/资源,以便对象被垃圾收集,诸如此类)。
如果不更具体地说明你想要实现的目标,就很难给出一个更合适的答案。