nobug
作为一个程序员,每天都会遇到问题、调试代码。常见的调试一般是加日志、打断点。在java中添加日志,每次都要编译,极其不便。java作为一门成熟的语言,怎么能没有成熟的机制?我们平时一般会用IDE自带的调试工具,eclipse、Intellij 等。本文将讲解一下java debug 体系的基础知识。
intellij
1 JPDA (Java platform debug Architecture)体系介绍
我们在调试的过程中,一般需要一些方法来观察和测试运行态中的环境信息,比如变量、状态、jvm 状态、堆栈信息等。这些通过JPDA都可以搞到。
2 JPDA结构
JPDA结构
JPDA定义了一个完整独立的体系,它由三个相对独立的层次共同组成,而且规定了三者之间的交互方式。这三个层次由低到高依次是Java 虚拟机工具接口(JVMTI),Java 调试线协议(JDWP)以及 Java 调试接口(JDI)。这三个模块把调试过程分解成几个很自然的概念:调试者(debugger)和被调试者(debuggee),以及他们中间的通信器。
3 JPDA三层结构的交互
交互
基本交互可以分为如下步骤:
3.1、jvmti 相关的步骤
jvm启动,注册JVMTI:jvm启动时,会检查对应的jvm参数,加载jvmti。
jvm启动, jdwp以agent的方式加载,并且设置对应的callback函数。启动jdwp的监听socket ;并且会初始化一个eventQueue实例,用户后续跟jdi 进行event交互。event 共有18种。(这个过程可以在启动时加载,也可以jvm其中之后以attach的方式加载 你假笨的jvm attach机制实现)。具体的jvm启动过程可以看一些我的这篇文章:jvm启动 ;
3.2、JDI相关的步骤
上述步骤主要描述了一下jvmti 相关的启动,下面讲一下JDI相关的步骤(以断点调试为例):
从Intellij建立Remote debug, 此时就是建立了一个socket连接(上面步骤中jdwp agent 已经建立了socket ,等待客户端的连接)
建立完连接,第一件事情就是双方进行handshake 交互,彼此之间确认对方使用的都是jdwp协议。
Intellij 设置断点,就是通过jdi 的eventRequestManage 生成一个类型为breakpoint event 并且带有filter(保证只在特定地方生效)的eventRequest, 然后按照jdwp协议组装成command ,发送给目标jvm.
3.3、目标jvm的处理
目标jvm接收到来自调试端的command 指令,会解析指令
目标jvm 运行,当触发breakpoint event 且满足调试端的filter 规则时 ,将这个breakpoint event加入到breakpoint eventSet 中
然后 eventQueue 实例会将eventSet 按照FIFO的顺序返回给调试端。当然返回之前会将结果按照jdwp协议组装成reply 命令返回。
4 总结