- 如果 JDI/JDWP 所包含的功能不满足我们的需求,例如堆栈分析,那么我们可以直接通过 JVMTI 来实现我们想要的功能。
JVMTI 规范所对应的功能是最完整的,而 JDWP 仅支持部分功能,JDI 则仅支持调试相关的功能。在功能上,是父子集的关系。
通信机制
调试器与被调试JVM之间需要通过一定的方式进行通信,通信的机制主要包括两部分
-
连接器(Connector)
-
通信方式(Transport)
连接器是指调试器与被调试 JVM 之间的一个连接,JPDA 在 JDI 这一层面实现了连接器。
通信方式是指调试器与被调试 JVM 之间的数据交换方式和通信报文格式,JPDA 在 JDWP 中定义了报文规范。
连接器
连接器有三种:
-
Listening:调试器监听来自被调试 JVM 的连接;
-
Attaching:调试器连接上一个已经处于运行状态的被调试 JVM;
-
Launching:调试器直接亲手启动被调试 JVM,此时调试器与被调试代码实际上是运行在同一个 JVM 中的;
通信方式
调试器与被调试 JVM 之间的数据交换方式,有两种:
- 基于 Socket 网络连接,主要用于远程调试,即调试器和被调试 JVM 不在同一台机器上;
- 基于操作系统共享内存的通信,主要用于调试器和被调试 JVM 在同一台机器上的情况;
配置
调试器和被调试 JVM 在启动的时候, 都需要通过设置 JVM 参数来让它具有调试的能力或者可被调试的能力。
对于 JDK5 及以上的版本,参数格式为:-agentlib:jdwp={子配置项}
对于 JDK5 以前的版本,参数格式为:-Xdebug
以及 -Xrunjdwp:{子配置项}
。
而子配置项,包括:
-
transport:数据交换方式,可选:
dt_socket
和dt_shmem
,分别代表 socket 网络通信和共享内存通信 -
Address:标识一个对端的地址,格式为:
{ip}:{port}
-
server:标识自己是调试者还是被调试者,调试者配置为:
n
,被调试着配置为:y
-
suspend:只有被调试者才需要配这个参数,当配置为
y
的时候,代表等待调试者连接上来才真正启动 Java 应用;配置为n
时,则直接启动 Java 应用。
这里的 Java 应用,是相对于 JVM 来说的,假如把 JVM 看成一个平台,那我们写的代码就是一个 Java 应用。JVM 已经启动,但我们的应用代码还没有跑起来,这种情况在上文的语境中,我们叫做 Java 应用还没启动。
配置示例:
- 被调试者开启远程调试监听:
-agentlib:jdwp=transport=dt_socket,address=localhost:7007,server=y,suspend=y
复制代码
- 被调试者开启本地共享内存调试监听:
-agentlib:jdwp=transport=dt_shmem,server=y,suspend=n
复制代码
- 调试者远程连接被调试者:
-agentlib:jdwp=transport=dt_socket,address=localhost:7007,server=n,suspend=y
复制代码
- 调试者基于共享内存方式连接被调试者:
-agentlib:jdwp=transport=dt_shmem, address=
复制代码
- 调试者基于共享内存方式启动被调试者:
-agentlib:jdwp=transport=dt_shmem,server=y,onuncaught=y,launch=d:\bin\debugstub.exe
复制代码
被调试者基于共享内存的监听启动后,共享内存地址将会打印到控制台上。调试者配置时需要配置这个共享内存的地址
JDI
功能
-
提供了跟调试相关的 Java API;
-
能够获取一个正在运行的 JVM 的状态,包括:类,数组,接口,基本类型以及这些类型的对象数量;
-
与执行相关的控制,例如暂停和恢复线程;
-
设置断点,监听异常的发生、类加载、线程创建等;
-
提供不同的连接器实现,例如基于 socket 的远程连接器和基于共享内存的本地连接器;
技术架构
-
提供事件机制
-
对 JDWP 协议的编解码
用法
要使用 JDI 的功能,需要依赖 JDK 自带的 tools.jar
这个工具包,JDI 相关的代码处于 com.sun.jdi
这个包下面。
一个大致的使用步骤如下所示:
-
获取一个
VirtualMachine
实例 -
从
VirtualMachine
实例中获取一个Connector
-
使用
VirtualMachine
的EventRequestManager
来监听我们感兴趣的事件
事件机制代码示例:
EventRequestManager em=vm.eventRequestManager();
MethodEntryRequest meR=em.createMethodEntryRequest();
meR.addClassFilter(“mypckg.*”);
meR.enable();
EventQueue eventQ=vm.eventQueue();
while (running) {
EventSet eventSet=null;
eventSet=eventQ.remove();
EventIterator eventIterator=eventSet.eventIterator();
while (eventIterator.hasNext()) {
Event event=eventIterator.nextEvent();
if (event instanceof MethodEntryEvent) {
// process this event
}
vm.resume();
}
}
复制代码
JDWP
报文格式
请求报文:
响应报文:
命令集
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
最后希望可以帮助到大家!
千千万万要记得:多刷题!!多刷题!!
之前算法是我的硬伤,后面硬啃了好长一段时间才补回来,算法才是程序员的灵魂!!!!
篇幅有限,以下只能截图分享部分的资源!!
(1)多线程(这里以多线程为代表,其实整理了一本JAVA核心架构笔记集)
(2)刷的算法题(还有左神的算法笔记)
(3)面经+真题解析+对应的相关笔记(很全面)
(4)视频学习(部分)
ps:当你觉得学不进或者累了的时候,视频是个不错的选择
在这里,最后只一句话:祝大家offer拿到手软!!
面硬啃了好长一段时间才补回来,算法才是程序员的灵魂!!!!
篇幅有限,以下只能截图分享部分的资源!!
(1)多线程(这里以多线程为代表,其实整理了一本JAVA核心架构笔记集)
[外链图片转存中…(img-1PaMJIZp-1711948041518)]
(2)刷的算法题(还有左神的算法笔记)
[外链图片转存中…(img-N1vrCm0q-1711948041518)]
(3)面经+真题解析+对应的相关笔记(很全面)
[外链图片转存中…(img-59WmOif6-1711948041519)]
(4)视频学习(部分)
ps:当你觉得学不进或者累了的时候,视频是个不错的选择
在这里,最后只一句话:祝大家offer拿到手软!!