https://www.cnblogs.com/xiaojiesir/p/15652619.html

Java 平台调试体系(Java Platform Debugger Architecture,JPDA),由三个相对独立的层次共同组成。这三个层次由低到高分别是 Java 虚拟机工具接口(JVMTI)、Java 调试连接协议(JDWP)以及 Java 调试接口(JDI)。

模块 层次 编程语言 作用
JVMTI 底层 C 获取及控制当前虚拟机状态
JDWP 中间层 C 定义 JVMTI 和 JDI 交互的数据格式
JDI 高层 Java 提供 Java API 来远程控制被调试虚拟机

服务端 JVM 配置

如何在 JVM 中启用 JDWP,以供远程调试。 假设主启动类是 com.xxx.Test。

在 Windows 机器上:

java -Xdebug -Xrunjdwp:transport=dt_shmem,address=debug,server=y,suspend=y com.xxx.Test

在 Solaris 或 Linux 操作系统上:

java -Xdebug -Xrunjdwp:transport=dt_socket,address=8888,server=y,suspend=y com.xxx.Test

-Xdebug:通知JVM工作在debug模式下;

-Xrunjdwp:通知JVM使用(java debug wire protocol)来运行调试环境;

transport:传输方式,Linux 采用监听Socket端口连接方式(也可以采用 dt_shmem共享内存方式,只限于windows机器,并且服务提供端和调试端只能位于同一台机);

server:server=y表示当前是调试服务端,=n表示当前是调试客户端;

suspend=y 会让 Java 进程启动时先挂起,等到有调试器连接上以后继续执行程序,一般用于被动连接;suspend=n 的话,则此 Java 进程会直接执行,但是我们可以随时通过调试器连上进程,一般用于设置主动连接。

就是说,比如说我们启动一个 Web 服务器进程,当这个值是 y 的时候,服务器的 JVM 初始化以后不会启动 Web 服务器,会一直等到我们用 IDEA 或 Eclipse、JDB 等工具连上这个 Java 进程后,再继续启动 Web 服务器。而如果是 n 的话,则会不管有没有调试器连接,都会正常运行。

通过这些启动参数,Test 类将运行在调试模式下,并等待调试器连接到 JVM 的调试地址:在 Windows 上是 Debug,在 Oracle Solaris 或 Linux 操作系统上是 8888 端口。

IDEA 中 Debug 模式启动的程序,自动设置了类似的启动选项。

JDB

启用了 JDWP 之后,可以使用各种客户端来进行调试/远程调试。比如 JDB 调试本地 JVM:

jdb -attach 'debug'
jdb -attach 8888

当 JDB 初始化并连接到 Test 之后,就可以进行 Java 代码级(Java-level)的调试。

但是 JDB 调试非常麻烦,比如说几个常用命令:

\1. 设置断点:

stop at 类名:行号 

\2. 清除断点:

clear at 类名:行号 

\3. 显示局部变量:

localx

\4. 显示变量 a 的值:

print a

\5. 显示当前线程堆栈:

wherei

\6. 代码执行到下一行:

next

\7. 代码继续执行,直到遇到下一个断点:

cont

可以看到使用 JDB 调试的话非常麻烦,所以我们一般还是在开发工具 IDE(IDEA、Eclipse)里调试代码。

开发工具 IDEA 中使用远程调试

远程调试

主动连接调试:服务端配置监控端口,本地IDE连接远程监听端口进行调试,一般调试问题用这种方式。

被动连接调试:本地IDE监听某端口,等待远程连接本地端口。一般用于远程服务启动不了,启动时连接到本地调试分析。

下面介绍 IDEA 中怎样使用远程调试。与常规的 Debug 配置类似,进入编辑:

添加 Remote(不是 Tomcat 下面的那个 Remote Server):

选择mode

调试模式:默认为Attach ;

  Attach :此种模式下,调试服务端(被调试远程运行的机器)启动一个端口等待我们(调试客户端)去连接;

  listen :此种模式下,是我们(调试客户端)去监听一个端口,当调试服务端准备好了,就会进行连接。

选择transport

传输方式,默认为Socket ;

套接字:MACOS,Linux的系统使用此种传输方式;

共享内存:WINDOWS系统使用此种传输方式。

然后配置端口号,比如 8888。

然后点击应用(Apply)按钮。

点击 Debug 的那个按钮即可启动远程调试,连上之后就和调试本地程序一样了。当然,记得加断点或者条件断点。

注意:远程调试时,需要保证服务端 JVM 中运行的代码和本地完全一致,否则可能会有莫名其妙的问题。

细心的同学可能已经发现,IDEA 给出了远程 JVM 的启动参数,建议使用 agentlib 的方式:

-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=8888

远程调试代码不仅在开发程序的过程中非常有用,而且实际生产环境,有时候我们无法判断程序运行的过程中出现了什么问题,到时运行结果跟期望值不一致,这时候就可以使用远程调试功能连接到生产环境,从而可以追踪导致执行过程中的哪个步骤出了问题。

JVM 为什么可以让不同的开发工具和调试器都连接上进行调试呢?因为它提供了一套公开的调试信息的交互协议,各家厂商就可以根据这个协议去实现自己的调试图形工具,进而方便 Java 开发人员的使用。下面就简单谈谈这个协议。

JDWP 协议规范

JDWP 全称是 Java Debug Wire Protocol,中文翻译为“Java 调试连接协议”,是用于规范调试器(Debugger)与目标 JVM 之间通信的协议。

JDWP 是一个可选组件,可能在某些 JDK 实现中不可用。

JDWP 支持两种调试场景:

  • 同一台计算机上的其他进程
  • 远程计算机上

与许多协议规范的不同之处在于,JDWP 只规定了具体的格式和布局,而不管你用什么协议来传输数据。

JDWP 实现可以只使用简单的 API 来接受不同的传输机制。具体的传输不一定支持各种组合。

JDWP 设计得非常简洁,容易实现,而且对于未来的升级也足够灵活。

当前,JDWP 没有指定任何传输机制。将来如果发生变更,会在单独的文档中来进行规范。

JDWP 是 JPDA 中的一层。JPDA(Java Platform Debugger Architecture,Java 平台调试器体系结构)架构还包含更上层的 Java 调试接口(JDI,Java Debug Interface)。JDWP 旨在促进 JDI 的有效使用;为此,它的许多功能都是量身定制的。

对于那些用 Java 语言编写的 Debugger 工具来说,直接使用 JDI 比起 JDWP 更加方便。

JDWP 握手过程

连接建立之后,在发送其他数据包之前,连接双方需要进行握手:

握手过程包括以下步骤:

  • Debugger 端向目标 JVM 发送 14 个字节,也就是包括 14 个 ASCII 字符的字符串 "JDWP-Handshake"。
  • VM 端以相同的 14 个字节答复:JDWP-Handshake。

JDWP 数据包

JDWP 是无状态的协议,基于数据包来传输数据。包含两种基本的数据包类型:命令包(Command Packet)和应答包(Reply Packet)。

调试器和目标 VM 都可以发出命令包,调试器可以用命令包来从目标 VM 请求相关信息或者控制程序的执行,目标 VM 可以将自身的某些事件(例如断点或异常)用命令数据包的方式通知调试器。

应答包仅用于对命令包进行响应,并且标明该命令是成功还是失败。 应答包还可以携带命令中请求的数据(例如字段或变量的值)。当前,从目标 VM 发出的事件不需要调试器的应答。

JDWP 是异步的,在收到某个应答之前,可以发送多个命令包。

命令包和应答包的 header 大小相等。这样使传输更易于实现和抽象。每个数据包的布局如下所示。

命令包(Command Packet)

  • Header

    • length(4 bytes)
    • id(4 bytes)
    • flags(1 byte)
    • command set(1 byte)
    • command(1 byte)
  • data(长度不固定)

应答包(Reply Packet)

  • Header

    • length(4 bytes)
    • id(4 bytes)
    • flags(1 byte)
    • error code(2 bytes)
  • data(Variable)

可以看到,这两种数据包的 Header 中,前三个字段格式是相同的。

通过 JDWP 发送的所有字段和数据都应采用大端字节序(big-endian)。大端字节序的定义请参考《Java 虚拟机规范》。

数据包字段说明

通用 Header 字段

下面的 Header 字段是命令包与应答包通用的。

length

length 字段表示整个数据包(包括 header)的字节数。因为数据包 header 的大小为 11 个字节,因此没有 data 的数据包会将此字段值设置为 11。

id

id 字段用于唯一标识每一对数据包(command/reply)。应答包 id 值必须与对应的命令包 ID 相同。这样异步方式的命令和应答就能匹配起来。同一个来源发送的所有未完成命令包的 id 字段必须唯一。(调试器发出的命令包,与 JVM 发出的命令包如果 ID 相同也没关系。) 除此之外,对 ID 的分配没有任何要求。对于大多数实现而言,使用自增计数器就足够了。id 的取值允许 2^32 个数据包,足以应对各种调试场景。

flags

flags 标志用于修改命令的排队和处理方式,也用来标记源自 JVM 的数据包。当前只定义了一个标志位 0x80,表示此数据包是应答包。协议的未来版本可能会定义其他标志。

命令包的 Header

除了前面的通用 Header 字段,命令包还有以下请求头。

command set

该字段主要用于通过一种有意义的方式对命令进行分组。Sun 定义的命令集,通过在 JDI 中支持的接口进行分组。例如,所有支持 VirtualMachine 接口的命令都在 VirtualMachine 命令集里面。命令集空间大致分为以下几类:

  • 0-63:发给目标 VM 的命令集
  • 64-127:发送给调试器的命令集
  • 128-256:JVM 提供商自己定义的命令和扩展。

command

该字段用于标识命令集中的具体命令。该字段与命令集字段一起用于指示应如何处理命令包。更简洁地说,它们告诉接收者该怎么做。具体命令将在本文档后面介绍。

应答包的 Header

除了前面的通用 Header 字段,应答包还有以下请求头。

error code

此字段用于标识是否成功处理了对应的命令包。0 值表示成功,非零值表示错误。返回的错误代码由具体的命令集/命令规定,但是通常会映射为 JVM TI 标准错误码。

Data

每个命令的 Data 部分都是不同的。相应的命令包和应答包之间也有所不同。例如,请求命令包希望获取某个字段的值,可以在 Data 中填上 object ID 和 field ID。应答包的 Data 字段将存放该字段的值。

JDWP 中常用的数据类型

通常,命令或应答包的 Data 字段格式由具体的命令规定。Data 中的每个字段都是(Java 标准的)大端格式编码。下面介绍每个 Data 字段的数据类型。

大部分 JDWP 数据包中的数据类型如下所述。

Name Size
byte 1 byte
boolean 1 byte
int 4 bytes
long 8 bytes
objectID 由具体的 JVM 确定,最多 8 字节
tagged-objectID objectID 的大小 +1 字节
threadID 同 objectID
threadGroupID 同 objectID
stringID 同 objectID
classLoaderID 同 objectID
classObjectID 同 objectID
arrayID 同 objectID
referenceTypeID 同 objectID
classID 同 referenceTypeID
interfaceID 同 referenceTypeID
arrayTypeID 同 referenceTypeID
methodID 由具体的 JVM 确定,最多 8 字节
fieldID 由具体的 JVM 确定,最多 8 字节
frameID 由具体的 JVM 确定,最多 8 字节
location 由具体的 JVM 确定
string 长度不固定
value 长度不固定
untagged-value 长度不固定
arrayregion 长度不固定

不同的 JVM 中,Object IDs、Reference Type IDs、Field IDs、Method IDs 和 Frame IDs 的大小可能不同。

通常,它们的大小与 JNI 和 JVMDI 调用中用于这些项目的 native 标识符的大小相对应。这些类型中最大的 size 为 8 个字节。当然,调试器可以使用 "idSizes" 这个命令来确定每种类型的大小。

如果 JVM 收到的命令包里面含有未实现(non-implemented)或无法识别(non-recognized)的命令/命令集,则会返回带有错误码 NOT_IMPLEMENTED 的应答包。

[转帖]Java 平台调试体系的更多相关文章

  1. 深入 Java 调试体系: 第 1 部分,JPDA 体系概览

    JPDA 概述 所有的程序员都会遇到 bug,对于运行态的错误,我们往往需要一些方法来观察和测试运行态中的环境.在 Java 程序中,最简单的,您是否尝试过使用 System.out.println( ...

  2. 深入 Java 调试体系: 第 1 部分,初探JPDA 体系

    JPDA(Java Platform Debugger Architecture)是 Java 平台调试体系结构的缩写,通过 JPDA 提供的 API,开发人员可以方便灵活的搭建 Java 调试应用程 ...

  3. Atitit.获取swing ui 按钮控件的id 与名字 与JPDA 调试体系

    Atitit.获取swing ui 按钮控件的id 与名字 与JPDA 调试体系 1. Swing Inspector是一个Java Swing/AWT用户界面分析和调试工具,功能与firebug类似 ...

  4. 使用java远程调试技术监控代码运行

    JAPA介绍 JPDA(Java Platform Debugger Architecture)是 Java 平台调试体系结构的缩写,通过 JPDA 提供的 API,开发人员可以方便灵活的搭建 Jav ...

  5. linux下的java远程调试jpda+tomcat

    项目放到linux服务器了,服务器的环境或者数据可能和我们本地不一样,这个时候我们可能需要远程的断点进行调试,来查看请求过程中的各个变量的值.这里我们的应用服务器用的tomcat5.5.17 这个时候 ...

  6. [置顶] 遵循Java EE标准体系的开源GIS服务平台之二:平台部署

    传送门 ☞ 系统架构设计 ☞ 转载请注明 ☞ http://blog.csdn.net/leverage_1229 传送门 ☞ GoF23种设计模式 ☞ 转载请注明 ☞ http://blog.csd ...

  7. [置顶] 遵循Java EE标准体系的开源GIS服务平台架构

    传送门 ☞ 系统架构设计 ☞ 转载请注明 ☞ http://blog.csdn.net/leverage_1229 传送门 ☞ GoF23种设计模式 ☞ 转载请注明 ☞ http://blog.csd ...

  8. Java开发中的高频Collections用法总结与Java平台实现源代码查看方式

    一生二,二生三,三生万物,基础永远是一个计算机人的立身之本,相信看到这篇文章的人一般都知道数据结构这门课程,要不也不会找到我的这篇文章.数据结构这门课程的分析奠定了工程师对各种平台中的容器类,集合类的 ...

  9. .NET平台技术体系梳理+初学者学习路径推荐+我们的愿景与目标

    文章出自:http://www.cnblogs.com/ice-river/p/3475041.html 一 .NET平台技术体系梳理 .NET平台应用领域众多(桌面开发,web开发,移动开发),不断 ...

  10. .NET平台技术体系

    .NET平台技术体系梳理+初学者学习路径推荐+我们的愿景与目标 一 .NET平台技术体系梳理 .NET平台应用领域众多(桌面开发,web开发,移动开发),不断有新的编程爱好者开始学习或从其他平台转移到 ...

随机推荐

  1. MySQL进阶篇:详解索引概述

    2.1 MySQL进阶篇:第二章_二.一_索引概述 2.1.1 介绍 索引(index)是帮助MySQL高效获取数据的数据结构(有序).在数据之外,数据库系统还维护着满足 特定查找算法的数据结构,这些 ...

  2. 【华为云技术分享】解密如何使用昇腾AI计算解决方案构建业务引擎

    摘要:昇腾AI计算解决方案以极致算力,端边云融合.全栈创新,开放生态的硬核实力.用户可以使用标准的Matrix接口实现业务引擎,对外释放昇腾AI加速能力. 从卷积神经网络中的矩阵乘法(GEMM)说起 ...

  3. 跨越全场景统一架构三大挑战,MindSpore亮出“四招”

    摘要:本文重点剖析全场景统一的AI框架的挑战和MindSpore的解决思路. 2020年的最后一天,MindSpore发布了1.1版本,1.1中很重要的特性是构建了端边云全场景统一的基础架构: htt ...

  4. 用100W+行代码贡献经验,带你了解如何参与OpenHarmony开源

    摘要:截至2022年11月,深开鸿共计参与共建OpenAtom OpenHarmony(以下简称OpenHarmony)社区16个SIG,其中4个为深开鸿主导,并累计贡献代码量超过百万行. 本文分享自 ...

  5. web自动化测试(1):再谈UI发展史与UI、功能自动化测试

    前言(废话) 行文前,安利下文章:<图形界面操作系统发展史--计算机界面发展历史回顾>.<再谈MV*(MVVM MVP MVC)模式的设计原理-封装与解耦> 1973年4月,X ...

  6. 大银行数字化升级之后,火山引擎 VeDI 这次要把能力带给中小金融机构

    更多技术交流.求职机会,欢迎关注字节跳动数据平台微信公众号,并进入官方交流群 数据技术是金融行业数字化转型的重要动力. 近年来,各大银行在全面推进数据技术建设上动作频频.比如,建设银行深化平台经营,依 ...

  7. Solon 编译打包怎样保持参数名不变?

    1.Java 项目 Java maven 项目 <plugin> <groupId>org.apache.maven.plugins</groupId> <a ...

  8. Kubernetes(K8S) 安装Nacos,报 No DataSource set

    原因,数据库为 MySQL 5.7 需要在yaml加上参数 mysql.db.param: "characterEncoding=utf8&connectTimeout=1000&a ...

  9. 在DataGrid中实现Button Command绑定

    在DataGrid中实现Button Command绑定 Command="{Binding editCommand}" 会默认查找UserList中对象的属性,而你的UserLi ...

  10. Spring Boot Admin 配置应用

    Spring Boot Admin 监控SpringBoot 服务的运行情况 https://codecentric.github.io/spring-boot-admin/2.3.0/#spring ...