我们正在开发一个应用程序,用于使用JDWP和JVMTI获取正在运行的Java应用程序的信息.Sun Java附带了JDWP的参考实现,因此使用agentlib -jdwp:将使用参考实现.我们的目标是研究JVMTI并编写JVMTI代理以获取具体细节.还创建一个Front端,用户可以使用该端请求有关正在运行的Java应用程序的特定信息.为此,我们必须编写JDWP的实现.虽然我们能够编写JVMTI代理并使用它从命令行附加到java应用程序.但我们的目标是将此信息发送到另一个java进程(前端).
所以我们有一个Java应用程序 - 前端查询来自JVMTI代理(后端)的信息.这些代理应该能够附加到我们要动态检查的运行java应用程序.关于如何做到这一点的任何想法?或者之前有人试过吗?
JDK具有用于远程/本地调试的内置Java api(com.sun.jdi.).
要快速开始使用api,您可以查看$ JDK_DIR\demo\jpda\examples.jar中的示例.[ 更多细节 ]
由于官方示例不太清楚,这里是可重复使用的示例(受此博客文章的启发):
VMAcquirer.java(连接经理)
public class VMAcquirer { public VirtualMachine connect(String host,int port) throws IOException { String strPort = Integer.toString(port); AttachingConnector connector = getConnector(); try { VirtualMachine vm = connect(connector,host, strPort); return vm; } catch (IllegalConnectorArgumentsException e) { throw new IllegalStateException(e); } } private AttachingConnector getConnector() { VirtualMachineManager vmManager = Bootstrap.virtualMachineManager(); for (Connector connector : vmManager.attachingConnectors()) { if("com.sun.jdi.SocketAttach".equals(connector.name())) return (AttachingConnector) connector; } throw new IllegalStateException(); } private VirtualMachine connect(AttachingConnector connector,String host,String port) throws IllegalConnectorArgumentsException, IOException { Mapargs = connector.defaultArguments(); Connector.Argument portArg = args.get("port"); portArg.setValue(port); Connector.Argument addressArg = args.get("hostname"); addressArg.setValue(host); return connector.attach(args); } }
Monitor.java(实际监控)
class Monitor { public static void main(String[] args){ VirtualMachine vm = new VMAcquirer().connect("192.168.0.x", 2600); System.out.println("name="+vm.name()); //Info about the remote VM System.out.println("description="+vm.description()); EventRequestManager erm = vm.eventRequestManager(); [...] //Send request using erm instance loopEventQueue(vm); //Start a loop to listen to the events received } public static void loopEventQueue(VirtualMachine vm) throws InterruptedException { EventQueue eventQueue = vm.eventQueue(); while (true) { EventSet eventSet = eventQueue.remove(); for (Event ev : eventSet) { if(ev instanceof MethodEntryEvent) { handleMethodEntryEvent(ev); } [...] } } } }
应用程序正在监视所需
java -Xdebug -Xrunjdwp:transport=dt_socket,address=2600,server=y,suspend=n ...
可通过JDWP获得的信息
跟踪方法调用和返回(可能用于进行分析或记录)
字段值更改
VM信息(请参阅示例中的name()和description())
评估表达式以执行任意代码