JVM远程调试功能开启,与原理

前言

以前有篇文章,讲解Tomcat开启远程调试功能,只是讲解了用法,以及Tomcat的作者书写脚本的初衷。原理没写,其实不是Tomcat的具有远程调试功能,是JVM虚拟机提供的能力,Java应用都能开启远程调试能力。上一篇文章:tomcat intellij远程调试

 

1. demo

随意写一个Java应用。

public class MapMain {
    public static void main(String[] args) {
        Map map = new HashMap<>();
        map.put("aa", "aa");
        map.put("bb", "bb");
        map.put("cc", "cc");
        map.put("dd", "dd");
        map.put("ff", "f");

        Set> entrySet = map.entrySet();
        for (Map.Entry entry : entrySet) {
            System.out.println(entry.getKey() + " ------ " + entry.getValue());
        }
    }
}

执行mvn package,打包成class文件

2. 通过JPDA开启调试

java -agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=9093 com.feng.map.demo.MapMain 

通过上面的执行方式,即可开启远程调试,并阻塞当前应用启动,知道远程连接接入

JVM远程调试功能开启,与原理_第1张图片

ide即可配置好远程JVM Debug

JVM远程调试功能开启,与原理_第2张图片

如上,笔者就可以远程调试了。

3. 原理分析

其实就是JVM参数开启远程debug,那么我们看看Tomcat是否是这样的。

3.1 Tomcat远程调试原理分析

直接查看Tomcat的bin目录的catalina.sh,win查看catalina.bat。Tomcat9版本

JVM远程调试功能开启,与原理_第3张图片

可以看到Tomcat也是使用我们在demo相同的参数开启远程debug能力的,jpda即Tomcat的catalina启动第一个参数,那么远程调试就是jpda?

3.2 Oracle官网说明

Java Platform Debugger Architecture (JPDA),JDK8的接口文档

参考上面Oracle官网的文档,实现调试能力的协议是JDWP协议

The Java Debug Wire Protocol (JDWP) is the protocol used for communication between a debugger and the Java virtual machine (VM) which it debugs (hereafter called the target VM). 

那么JVM的接口呢?

JVM远程调试功能开启,与原理_第4张图片

可以看到笔者是jdk8的文档,JVMDI接口已经移除了,那么现在使用的是JVMTI

The JVM tool interface (JVM TI) is a native programming interface for use by tools. It provides both a way to inspect the state and to control the execution of applications running in the Java virtual machine (JVM). JVM TI supports the full breadth of tools that need access to JVM state, including but not limited to: profiling, debugging, monitoring, thread analysis, and coverage analysis tools.

Note: JVM TI was introduced at JDK 5.0. JVM TI replaced the Java Virtual Machine Profiler Interface (JVMPI) and the Java Virtual Machine Debug Interface (JVMDI) which, as of JDK 6, are no longer provided.

大致意思是JVM TI可以支持访问JVM状态,包括调试,监控,线程分析等,替代了JVMPI和JVMDI

3.3 主要参数讲解

transport

指ide与运行的程序之间的协议:dt_socket: 采用socket方式连接,这是最常用的方式。

server

这个表示作为主动方还是被动方,即attach到jvm,还是监听jvm。attach为y,监听listen为n。

suspend

当应用启动后,是否阻塞应用直到被连接,默认值为y(阻塞),一般需要设置n,即不阻塞。但是当需要调试的程序是启动时执行的时候,需要设置y,方便启动调试

address

调试端口,即transport的端口,用于调试的socket连接,不能与应用使用的端口冲突。

其他

onthrow=,onuncaught=

指应用在抛出异常类或者未捕获异常时,退出调试。

 

总结

其实这些功能都是JVM提供的,类似Spring Boot与Tomcat或者其他Java应用也是JVM在后面起作用,这些都是封装JVM启动参数来达到调试的原理。IDE工具亦是如此,只是图形化做得很好。另外小技巧:当如果有防火墙时,可以临时使用8080这类已经开通的作为调试端口,用其他端口启动应用,调试结束就换参数即可,避免临时开墙的困扰。

 

你可能感兴趣的:(Java,jvm)