- 如果 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 已经启动,但我们的应用代码还没有跑起来,这种情况在上文的语境中,我 需要zi料+ 绿色徽【vip1024b】
们叫做 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;
总结
本文从基础到高级再到实战,由浅入深,把MySQL讲的清清楚楚,明明白白,这应该是我目前为止看到过最好的有关MySQL的学习笔记了,我相信如果你把这份笔记认真看完后,无论是工作中碰到的问题还是被面试官问到的问题都能迎刃而解!
MySQL50道高频面试题整理:
m.eventQueue();
while (running) {
EventSet eventSet=null;
总结
本文从基础到高级再到实战,由浅入深,把MySQL讲的清清楚楚,明明白白,这应该是我目前为止看到过最好的有关MySQL的学习笔记了,我相信如果你把这份笔记认真看完后,无论是工作中碰到的问题还是被面试官问到的问题都能迎刃而解!
MySQL50道高频面试题整理:
[外链图片转存中…(img-cNatMEms-1710351066937)]