4

我们正在开发一个应用程序,用于使用 JDWP 和 JVMTI 获取正在运行的 java 应用程序的信息。Sun Java 附带了 JDWP 的参考实现,因此使用 agentlib -jdwp: 将使用参考实现。我们的目标是研究 JVMTI 并编写 JVMTI 代理以获取具体细节。还创建了一个前端,用户可以使用它来请求有关正在运行的 java 应用程序的特定信息。为此,我们必须为 JDWP 编写实现。尽管我们能够编写 JVMTI 代理并使用它从命令行附加到 Java 应用程序。但我们的目标是将此信息发送到另一个 java 进程(前端)。

所以我们有一个 Java 应用程序——前端从 JVMTI 代理(后端)查询信息。这些代理应该能够附加到我们将要动态检查的正在运行的 java 应用程序。关于如何做到这一点的任何想法?或者以前有人试过吗?

4

1 回答 1

6

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 {

        Map<String, Connector.Argument> args = 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())
  • 评估表达式以执行任意代码

  • 于 2011-06-25T03:59:40.123 回答