所以我正在创建一个探查器应用程序。它有一个GUI类,用于控制分析器。它在运行时由2个部分组成: 1)用于控制的应用程序(GUI) 2)要加载到目标应用程序中的代理
它列出了PID,然后在VM上调用loadAgent()。所以我希望在主应用程序中完成所有逻辑。我的想法是从我的代理获取Instrumentation类的实例,然后通过反射调用回调方法。这将在主应用程序中将一个静态字段设置为Instrumentation实例,并通知主应用程序代理已成功加载。
我遇到的问题是我无法获取包含Instrumentation字段的主应用程序类。 Class.forName(String)隐式查找该应用程序的ClassLoader。另一种方法可以在另一个ClassLoader中查找类...不幸的是,我完全无法从主应用程序获取代理/目标应用程序的ClassLoader进入它!
我在Instrumentation或VirtualMachine类中看不到允许我这样做的方法。我还没有在互联网上找到任何这种性质的问题,这些问题也以令人满意的方式得到了回答。
我有一些想法...... A)如果ClassLoader有类似的Class.forName,我可以序列化ClassLoader并将串行化的字符串发送到套接字上,然后抓住它。到目前为止,我还没有发现任何类似的东西。 B)浏览代理中的ClassLoaders(有一个ClassLoader.getParent()方法......但这是我看到的唯一导航方法),并找到具有深度等于比较的正确ClassLoader。我甚至不知道从哪里开始..我希望我可以遍历VirtualMachines.list()并且我可以调用它。没有。 C)在主应用程序中加载代理程序,并以某种方式将该代理程序的特定实例传递给目标应用程序。由于它们是不同的ClassLoader,我只能假设这不起作用。尽管如此,我知道可能有办法做到这一点? D)在主应用程序中创建自定义ClassLoader并使用它加载目标应用程序。这里的问题是我想要完整"附加"这会阻止的功能。
我真的不想把所有的逻辑放在代理人身上,所以我想在走这条路之前我会问你们。谷歌搜索这一点并不富有成效。提前谢谢!
答案 0 :(得分:2)
我认为您误解了附加API 在这种情况下的工作原理。 attach API允许将代理从本地VM 进程注册到远程JVM 进程。附件后,远程VM在指定的线程中执行代理的agentmain
方法。代理不知道其附件进程,也无法将对象从远程堆传递到连接的VM堆。
此外,ClassLoader
s通常不可序列化。您宁愿需要通过进程之间的某个套接字来传递必要的信息。为此目的,本地VM可以例如将套接字地址作为参数传递给本地进程稍后等待从远程VM到达的信息的代理。在此原因中,您还应该考虑要从远程VM公开的信息。您可能不想发送可序列化的对象。