元月's blog 元月's blog
首页
  • 基础
  • 并发编程
  • JVM
  • Spring
  • Redis篇
  • Nginx篇
  • Kafka篇
  • Otter篇
  • Shardingsphere篇
  • 设计模式
  • MySQL
  • Oracle
  • 基础
  • 操作系统
  • 网络
  • 数据结构
  • 技术文档
  • Git常用命令
  • GitHub技巧
  • 博客搭建
  • 开发工具
更多

元月

临渊羡鱼,不如退而结网
首页
  • 基础
  • 并发编程
  • JVM
  • Spring
  • Redis篇
  • Nginx篇
  • Kafka篇
  • Otter篇
  • Shardingsphere篇
  • 设计模式
  • MySQL
  • Oracle
  • 基础
  • 操作系统
  • 网络
  • 数据结构
  • 技术文档
  • Git常用命令
  • GitHub技巧
  • 博客搭建
  • 开发工具
更多
  • 基础

  • 并发编程

  • JVM

    • Java的调试体系-JPDA架构
      • 一、前言
      • 二、JPDA是什么?
        • 1. JVM TI-Java 虚拟机工具接口
        • 2. JDWP-Java 调试协议
        • 3. JDI-Java 调试接口
      • 三、Java agent工作过程?
        • 1. 启动时载入
        • 2. 运行时载入
    • JVM整体结构和内存模型
    • 深度剖析JVM类加载机制
    • JVM对象创建与内存分配机制
    • JVM垃圾回收算法
    • JVM垃圾收集器一:Serial和Parallel收集器
    • JVM垃圾收集器二:CMS与三色标记算法详解
    • JVM垃圾收集器三:G1(Garbage First)
    • JVM垃圾收集器四:ZGC与颜色指针详解
    • JVM调优之常用的调优指令
    • JVM调优之常用的调优工具
    • Arthas:一款优秀的Java诊断工具
    • 亿级流量系统JVM实战
  • Java基础
  • JVM
元月
2022-06-21
目录

Java的调试体系-JPDA架构

# Java的调试体系-JPDA架构

# 一、前言

在日常工作中,往往会在开发环境或者线上环境遇到一些bug,这个时候,我们会在IDE工具(idea、eclipse)中开启debug模式进行断点调试,又或者使用一些第三方的工具,例如Arthas进行分析,定位问题。 大家是否有好奇过debug是什么原理?Arthas底层是通过什么方式实现的?Skywalking底层又是通过什么方式实现的呢?

# 二、JPDA是什么?

JPDA全称Java Platform Debugger Architecture,是一个多层的debug架构体系 ,这套体系为开发人员提供了一整套用于调试 Java 程序的 API。

JPDA由三层组成:

Components                          Debugger Interfaces

                /    |--------------|
               /     |     VM       |
 debuggee ----(      |--------------|  <------- JVM TI - Java VM Tool Interface(Java 虚拟机工具接口)
 被调试者       \     |   back-end   |
                \    |--------------|
                /           |
 comm channel -(            |  <--------------- JDWP - Java Debug Wire Protocol(Java 调试协议)
    通信器       \           |
                /    |--------------|
               /     | front-end    |
 debugger ----(      |--------------|  <------- JDI - Java Debug Interface(Java 调试接口)
  调试器        \     |      UI      |
                \    |--------------|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# 1. JVM TI-Java 虚拟机工具接口

JVMTI 的功能非常丰富,包含了 虚拟机中线程、内存 / 堆 / 栈,类 / 方法 / 变量,事件 / 定时器处理等等 20 多类功能,从功能上大致可以分为4类,如下:

  1. Heap:获取所有类信息,对象信息,对象引用关系,Full GC开始/结束,对象回收事件等;
  2. 线程与堆栈:获取所有线程信息,线程组信息,控制线程(start,suspend,resume,interrupt…), Thread Monitor(Lock),得到线程堆栈,控制出栈,方法强制返回,方法栈本地变量等;
  3. Class & Object & Method & Field 元信息:class信息,符号表,方法表,redefine class(hotswap), retransform class,object信息,fields信息,method信息等;
  4. 工具类:线程cpu消耗,classloader路径修改,系统属性获取等;

# 2. JDWP-Java 调试协议

2.1、通信机制 调试器与被调试JVM之间需要通过一定的方式进行通信,通信的机制主要包括两部分

  • 连接器(Connector)连接器是指调试器与被调试 JVM 之间的一个连接,JPDA 在 JDI 这一层面实现了连接器,连接器有三种:
    1. Listening 连接器:调试器监听来自被调试 JVM 的连接;
    2. Attaching 连接器:调试器连接上一个处于运行状态的被调试 JVM;
    3. Launching 连接器:调试器直接亲手启动被调试 JVM,此时调试器与被调试代码运行在同一个 JVM 中
  • 通信方式(Transport)通信方式是指调试器与被调试 JVM 之间的数据交换方式和通信报文格式,JPDA 在 JDWP 中定义了报文规范。

# 3. JDI-Java 调试接口

# 三、Java agent工作过程?

Java Agent 又叫做 Java 探针,是在 JDK1.5 引入的一种可以动态修改 Java 字节码的技术。在Java 类编译之后形成的字节码被 JVM 执行之前获取这些字节码信息,并且通过字节码转换器对这些字节码进行修改,来完成一些额外的功能。

也可以认为这个功能是 Java 虚拟机提供的一整套后门,通过这套后门可以对虚拟机方方面面进行监控与分析,甚至干预虚拟机的运行。

JVMTI有两种启动方式:启动时载入、运行时载入

# 1. 启动时载入

我们查看java命令的帮助文档java -h,会发现三个选项agentlib,agentpath,javaagent,我们重点看下javaagent,其中Skywalking就是通过这种方式载入,如下:

# load native agent library <libname>, e.g. -agentlib:jdwp
# see also -agentlib:jdwp=help
-agentlib:<libname>[=<options>]
                  
# load native agent library by full pathname
-agentpath:<pathname>[=<options>]         
              
# -javaagent:/xxx/xxx/skywalking-agent.jar
# load Java programming language agent, see java.lang.instrument
-javaagent:<jarpath>[=<options>]
1
2
3
4
5
6
7
8
9
10

启动时载入,处于虚拟机初始化的早期,在这个时间点上:

  1. 所有的 Java 类都未被初始化;
  2. 所有的 Java 对象实例都未被创建;
  3. 因而,没有任何 Java 代码被执行;

但在这个时候,我们已经可以:

  1. 操作 JVMTI 的 Capability 参数;
  2. 使用系统参数;

# 2. 运行时载入

通过attach api,这是一套纯Java的API,它负责动态地将dynamic module attach到指定进程id的Java进程内并触发回调。其中Arthas就是通过这种方式载入的,例子如下

import java.io.IOException;
import com.sun.tools.attach.VirtualMachine;

public class VMAttacher {
    public static void main(String[] args) throws Exception {
         // args[0]为java进程id
         VirtualMachine virtualMachine = com.sun.tools.attach.VirtualMachine.attach(args[0]);
         // args[1]为共享库路径,args[2]为传递给agent的参数
         virtualMachine.loadAgentPath(args[1], args[2]);
         virtualMachine.detach();
    }
}
1
2
3
4
5
6
7
8
9
10
11
12

本文主要参考文档:

JAVA-JPDA官网文档 (opens new window)、浅谈JPDA中JVMTI模块 (opens new window)

基于Java Instrument的Agent实现 (opens new window)、JAVA进阶之Agent (opens new window)

#JVM
JMM之volatile的底层实现原理详解
JVM整体结构和内存模型

← JMM之volatile的底层实现原理详解 JVM整体结构和内存模型→

最近更新
01
otter二次开发-支持按目标端主键索引Load数据
08-03
02
mvnw简介
06-21
03
gor流量复制工具
06-03
更多文章>
Theme by Vdoing | Copyright © 2022-2024 元月 | 粤ICP备2022071877号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式