[TOC]
1. 前言
我们在使用idea启动debug时可以做好多事情,看变量的值; 随处打断点; 计算变量的值等等, 这些功能全都依赖了java的调试体系JPDA(Java Platform Debugger Architecture), 而java也提供了命令行级别的调试
2. 调试使用
关键命令
javac -g src/HelloJDB.java
-g 表示展示调试信息
这样就启动了程序,然后打开调试程序
jdb HelloJDB.class
使用JDB调试Java程序 - 娄老师 - 博客园 (cnblogs.com)
由此可见,idea那么丰富的调试功能基本来源jvm
3. JPDA
JPDA 由三个规范组成:JVMTI(JVM Tool Interface)、JDWP(Java Debug Wire Protocol)、JDI(Java Debug Interface)
这三个规范的层次由低到高分别是 JVMTI、JDWP、JDI
这三个规范把调试过程分解成几个概念:调试者(debugger)、被调试者(debuggee)、以及它们中间的通信器
JPDA 被抽象为三层实现。其中 JVMTI 是 JVM 对外暴露的接口。JDI 是实现了 JDWP 通信协议的客户端,调试器通过它和 JVM 中被调试程序通信。
模块 | 层次 | 编程语言 | 作用 |
---|---|---|---|
JVMTI | 底层 | C | 获取及控制当前虚拟机状态 |
JDWP | 中介层 | C | 定义 JVMTI 和 JDI 交互的数据格式 |
JDI | 高层 | Java | 提供 Java API 来远程控制被调试虚拟机 |
IDEA 的 debug 怎么实现?出于这个好奇心,我越挖越深! - 知乎 (zhihu.com)
Java-JPDA 概述 - 江湖小小白 - 博客园 (cnblogs.com)
Q&A
为什么在debug中没有重排序了?
为了保证代码的顺序性,应该是做了禁止重排序的处理(包括指令/编译/内存重排序)
应该是在JVMTI这一层处理的,因为它包含了 虚拟机中线程、内存、堆、栈、类、方法、变量,事件、定时器处理等等诸多功能
在debug中怎么实现动态代码的?(改了代码无需重启,甚至直接修改变量值)
使用了动态字节码技术ASM, 使得代码的修改能直接被jvm识别并执行
动态字节码技术还有很多,比如CGlib/Aspectj/agent等等, 动态字节码技术详解
我们在启动被 Debug 的 JVM 时,必须添加参数
-agentlib:jdwp=transport=dt_socket,suspend=y,address=localhost:3333
,而 -agentlib 选项就指定了我们要加载的 Java Agent,jdwp 是 agent 的名字,在 linux 系统中,我们可以在 jre 目录下找到 jdwp.so 库文件。Java 的调试体系 jdpa 组成,从高到低分别为
jdi->jdwp->jvmti
,我们通过 JDI 接口发送调试指令,而 jdwp 就相当于一个通道,帮我们翻译 JDI 指令到 JVM TI,最底层的 JVM TI 最终实现对 JVM 的操作。