JPDA 架构研究3 - JDWP层的数据包

引入:

现在我们来看JDWP层的数据包。源码在JDK中很容易找到,它定义$JAVA_HOME/include/jdwpTransport.h 头文件中。

分析:

Part 1: 握手过程 (handshake )

握手包发生在Debugger(JDI端)和Target VM(JVMTI端)的传输层连接建立,并且在发送任何实际数据报之前完成的。它过程如下:

a. Debugger会发送14个字节的握手请求到Target VM,这个包的内容是14字节的ASCII字符串 “JDWP-Handshake”

b. Target VM会返回14个字节的握手响应到Debugger,其内容也是14字节的ASCII字符串,和刚才一样,“JDWP-Handshake"

这样的主要作用是为了确保 Debugger和Target VM之间通信正常。

Part2:发送具体调试请求和获得响应阶段:命令包(Command Packet)和响应包(Reply Packet)

从许多文档中, 我概括了JDWP层包的一些特点:

(1)包是无状态的

(2)命令包可以通过Debugger或者Target VM来发送。

对于从Debugger发送的命令包来说,它主要可以发送请求消息或者控制程序执行。

对于从Target VM发送的命令包来说,它可通知Debugger一些Target VM中的事件比如断点或者异常。

(3)响应包

响应包用于对于某命令包的响应,它总用于返回命令的成功或失败,并且可以携带命令包中包含的数据。

对于从Debugger发送的命令包,一般总会有响应包。

对于从Target VM发送的命令包,无需要响应包。

(4)JDWP平台对于数据包的发送是异步的,各个命令/响应包之间无顺序概念。

命令包的定义如下:

typedef struct {
    jint len;                  //命令包的长度:4字节,它是整个包的长度
    jint id;                   //命令包的ID: 4字节,用于表示命令包和对应响应包的配对,正因为此机制才可以让包是异步传输的。
    jbyte flags;           //命令包的标志位:1字节,用于定义该命令如何进队列/处理或者被打标记
    jbyte cmdSet;      //命令包的命令集:1字节,用于分组该命令 
                                //(0-63:表示Debugger往Target VM发送的命令)
                                // (64-127: 表示Target VM往Debugger发送的命令)
                                //(128-256: Vendor自定义命令)
    jbyte cmd;          //命令包中的命令:1字节
    jbyte *data;         //命令包中携带的数据
} jdwpCmdPacket;

响应包的定义如下:

typedef struct {
    jint len;                  //响应包的长度: 4字节
    jint id;                    //响应包的ID: 4字节,用于表示命令包和对应响应包的配对,正因为此机制才可以让包是异步传输的。
    jbyte flags;            //响应包的标志位:1字节,用于定义该命令如何进队列/处理或者被打标记
    jshort errorCode;  //响应包中的错误码:2字节,其中0表示成功,非0表示某种错误码,一般错误码会映射到JVMTI的返回码。
    jbyte *data;           //响应包中携带的数据
} jdwpReplyPacket;

补充说明:

(1)如果接收端接受到的命令包,其中携带的命令集或者命令是规范中未定义的,那么响应包的errorCode会被定义为NOT_IMPLEMENTED.

(2)ErrorCode定义如下:

typedef enum {
    JDWPTRANSPORT_ERROR_NONE = 0,
    JDWPTRANSPORT_ERROR_ILLEGAL_ARGUMENT = 103,
    JDWPTRANSPORT_ERROR_OUT_OF_MEMORY = 110,
    JDWPTRANSPORT_ERROR_INTERNAL = 113,
    JDWPTRANSPORT_ERROR_ILLEGAL_STATE = 201,
    JDWPTRANSPORT_ERROR_IO_ERROR = 202,
    JDWPTRANSPORT_ERROR_TIMEOUT = 203,
    JDWPTRANSPORT_ERROR_MSG_NOT_AVAILABLE = 204
} jdwpTransportError;
时间: 2024-08-06 11:54:30

JPDA 架构研究3 - JDWP层的数据包的相关文章

JPDA 架构研究4 - JDWP的传输接口

引入: 上一篇文章主要分析JDWP层传输的数据包的格式,这篇文章我们主要关注于JDWP层是如何传输的. 分析: 传输的具体实现是根据各个JVM自己实现,但是他们有个共同点就是都是用C/C++实现的,并且都实现了jdwpTransport.h (和上篇一样的这个文件).实现根据我们的知识可以得知是以dll文件(或者Unix平台下是so文件)的形式存在.因为我们从前面了解到,JDWP层有Agent负责在数据包和JVMTI的函数调用之间转换,所以顺理成章知道,传输层的DLL文件也必定会有一个onloa

JPDA 架构研究2 - JDWP代理

引入: 我们先从最重要的通信层讲起.通信层(JDWP) ,它的全称是Java Debug Wire Protocol.从"Wire"这词就可以看出,它主要是起到"连线"的作用,也就是说,它主要是起到把最靠近程序员的JDI(也就是调试器)和最靠近运行在虚拟机中的程序的JVMTI 连接在一起.因为彼此之间语言不通.比如说JDI这层,我们主要用的eclipse,它是JAVA语言编写的.而JVMTI是用来查询虚拟机状态的,而JAVA虚拟机是用C/C++写的,所以在语言不通的

JPDA 架构研究1- 整体架构

引入: 关于JPDA(Java Platform Debugger Architecture) 网上有很多讲解,例子.我也不重复发明轮子了,这组文章主要从实践的代码分析角度,仔细剖析这个平台的特点,以及这其中的一些问题澄清和误区. 实践: 如果我们从利用Java Remote Debug的功能来看待JPDA ,并且使用socket的通信方式的话,那么整个过程应该如下: 首先,你在要被调试的服务器上开启远程调试功能.以tomcat 为例: 你要么用命令catalina jpda start,它会启

JPDA 架构研究17 - JDI概览

引入: 前面用了很多篇幅来讨论JVMTI和JDWP部分,现在终于来看最靠近用户端部分了,JDI. 分析: a. JDI的基础知识 和JVMTI和JDWP不一样的是,JDI提供了一组接口,这些接口是纯JAVA编写的.他们主要是给开发环境IDE用的,虽然调试器的实现可以直接利用JDWP或者JVMTI,但是多了这一层则可以从用户的代码级别来定义要发送的请求和获取的信息. 本质上,Eclipse的调试器与目标VM之间的双向通信如下: 调试器将用户的操作转化为调试命令,命令通过链接被发送到前端运行目标程序

Linux网络之设备接口层:发送数据包流程dev_queue_xmit

转自:http://blog.csdn.net/wdscq1234/article/details/51926808 写在前面 本文主要是分析kernel-3.8的源代码,主要集中在Network的netdevice层面,来贯穿interface传输数据包的流程,kernel 博大精深,这也仅仅是一点个人愚见,作为一个笔记形式的文章,如有错误或者表述不当之处,还请大家留言批评指正,非常感谢! 主要涉及的file:kernel-3.18/net/core/dev.c kernel-3.18/net

JPDA 架构研究19 - JDI的连接模块

引入: 上文提到了JDI的Mirror机制,把整个目标虚拟机上的所有数据.类型.域.方法.事件.状态和资源,以及调试器发向目标虚拟机的事件请求等都映射成Mirror 对象.这里进一步讨论JDI的链接模块. 分析: 连接模块其主要目的是提供调试器(Debugger)到目标虚拟机(Target VM)之间的交互通道. 从连接的发起方来看:连接的发起方可以是调试器,也可以是目标虚拟机. 从连接的数量来看,一个调试器可以连接多个目标VM, 但是一个目标VM只可以连接一个调试器. 我们从调试器(Debug

JPDA 架构研究18 - JDI的Mirror机制

引入: 上篇文章从整体上来看待JDI协议,这里结合Eclipse的实现代码来讨论下JDI的Mirror机制. 分析: 镜像机制是将目标虚拟机上的所有数据.类型.域.方法.事件.状态和资源,以及调试器发向目标虚拟机的事件请求等都映射成 Mirror 对象.其思想和我们经常说的O/R Mapping一样,其主要思想就是把2个异构的系统中的事物统一起来. Mirror接口是JDI规范中定义的主接口,它位于com.sun.jdi包中: public abstract interface Mirror {

JPDA 架构研究20 - JDI的事件请求和处理模块

引入: 上文主要讲解了JDI的连接模块来建立Debugger到Target VM之间的连接,这里主要讲解事件请求和处理模块.它们都在com.sun.jdi.event和com.sun.jdi.request包中. 分析: Part 1:查看JDI中定义的事件类型 JDI中事件的接口叫Event . public abstract interface Event extends Mirror {   public abstract EventRequest request(); } 它定义了18种

JPDA 架构研究5 - Agent利用环境指针访问VM (内存管理篇)

引入: 我们在前面说到JVMTI的客户端Agent,又提到Agent通过环境指针来访问VM.这里就来看看环境指针到底有多大的访问VM的能力. 分类1:内存管理 a.Allocate. 分配内存 jvmtiError Allocate(jvmtiEnv* env,             jlong size,             unsigned char** mem_ptr) size:分配的字节数. mem_ptr:分配内存的首地址. b.Deallocate.释放内存,释放已经分配的内