使用JDWP和JVMTI获取正在运行的Java应用程序的信息

发布于 2024-08-15 07:47:56 字数 391 浏览 11 评论 0原文

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

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

We are developing an application for obtaining the information of a running java application using JDWP and JVMTI. Sun Java comes with a reference implementation of JDWP so using agentlib -jdwp: will use the reference implementation. Our aim is to study JVMTI and write JVMTI agents to get specific detail. Also creating a Front end using which the user can request for specific information about the running java application. For this we would have to write our implementation for JDWP. Though we were able to write JVMTI agents and use it to attach to the java application from the command line. But our aim is to send this information to another java process (Front End).

So we have a Java application- Front end querying for information from the JVMTI Agents (Back-End). These agents should be able to attach to the running java application we are going to inspect dynamically. Any ideas on how this can be done? Or has anyone tried this before?

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

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

发布评论

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

评论(1

阳光下慵懒的猫 2024-08-22 07:47:56

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())
  • 计算表达式以执行任意代码

  • The JDK has a built-in Java api for remote/local debug (com.sun.jdi.).

    To quickly start using the api, you can look at examples in $JDK_DIR\demo\jpda\examples.jar. [More details]


    Since the official examples are not so clear, here is reusable example (inspired by this blog post):

    VMAcquirer.java (Connection manager)

    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 (Actual monitoring)

    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);
                    }
                    [...]
                }
            }
        }
    }
    

    Required by the application being monitor

    java -Xdebug -Xrunjdwp:transport=dt_socket,address=2600,server=y,suspend=n ...
    

    Informations available through JDWP

  • Tracing method call and return (possibly for doing profiling or logging)
  • Field value changes
  • VM information (see name() and description() in the example)
  • Evaluate expression to execute arbitrary code

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