远程debug

一文读懂Java远程debug(Remote JVM Debug)

什么是远程debug

远程debug即对远程部署的内容进行debug

远程debug和本地debug 区别

本地debugidea本地启动 ——> idea 打断点 ——> postman 发送接口 ——> 进入断点
远程debug服务器上启动 ——> idea 监听启动 ——> idea 打断点 ——> 页面上操作发送接口 ——> 进入断点

应用场景

1 例如我们部署的项目在线上出现问题了,而我们又不知道具体是哪里出现问题,我们就可以使用远程debug进行排查问题。

2 当你在本地开发的时候,你需要调试服务器上的程序时,远程调试就显得非常有用。

3 开发环境正常测试过的功能在测试环境甚至生产环境下出现bug的情况。一般情况下,你可能需要多次重复这个过程(分析日志->猜测问题->加日志->部署->获取日志)来慢慢逼近问题。这时可以——远程调试——将程序在测试环境中以debug模式启动,在本机使用IDEA在工程中设置断点进行调试

远程debug原理

Java远程调试的原理是两个JVM之间通过debug协议进行通信,然后以达到远程调试的目的。两者之间可以通过socket进行通信

被debug的机器需要开启debug模式debug使用的客户端可以是idea。

远程调试原理

Java程序的执行过程- 分为以下几个步骤:Java的文件 - - 编译生成的类文件(class文件) - - JVM加载类文件 - - JVM运行类字节码文件 - - JVM翻译器翻译成各个机器认识的不同的机器码

Java 程序是运行在Java 虚拟机(JVM )上的,具有良好跨平台性,是因为Java程序统一以字节码的形式在JVM中运行不同平台的虚拟机统一使用这种相同的程序存储格式

因为都是类字节码文件,只要本地代码和远程服务器上的类文件相同两个JVM通过调试协议进行通信(例如通过插座在同一个端口进行通信),另外需要注意的时,被调试的服务器需要开启调试模式服务器端的代码和本地代码必须保持一致,则会造成断点无法进入的问题

debug java 远程 java远程debug原理_postman


这个架构其实质还是JVM,只要确保本地的Java的源代码与目标应用程序一致,本地的Java的源码就可以用插座连接到远端的JVM,进而执行调试。因此,在这种插座连接模式(下文介绍)下,本地只需要有源码,本地的Java的应用程序根本不用启动。

传输方式,默认为Socket ;

套接字:MACOS,Linux的系统使用此种传输方式;

共享内存:WINDOWS系统使用此种传输方式。

调试模式,默认为Attach ;

Attach :此种模式下,调试服务端(被调试远程运行的机器)启动一个端口等待我们(调试客户端)去连接;

Socket :此种模式下,是我们(调试客户端)去监听一个端口,当调试服务端准备好了,就会进行连接。

示例

k8s springcloud 多模块部署 项目

服务器上模块 pod.yml 文件修改

因为 k8s 中各个模块是通过 kubectl apply -f pod.yml 运行模块的,所以在 pod.yml 文件中有以下内容,可以使 jar 包以 debug 模式运行,开放 debug 端口

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myweb-user
  namespace: myweb
spec:
  ....
  template:
  ....
    spec:
      containers:
      - name: myweb-user
        image: "registry.xxxx.com/xxxx/myweb-user-application:3.0.0-test-dirty"
        imagePullPolicy: Always
        ports:
          - name: http
            containerPort: 8080
          - name: connect
            containerPort: 13000
----------重点是下面--------------------重点是下面-----------------------------           
          - name: debug
            containerPort: 12020
        command: ["java"]
        args: ["-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=12021", "-server", "-Djava.net.preferIPv4Stack=true", "-Dfile.encoding=utf-8", "-Xms3g", "-Xmx3g", "-XX:SurvivorRatio=2", "-XX:+UseParallelGC", "-XX:ParallelGCThreads=5", "-XX:MaxRAMPercentage=75.0", "-XX:+UseParallelOldGC", "-XX:+PrintGCDetails", "-XX:+PrintGCDateStamps", "-XX:+HeapDumpOnOutOfMemoryError", "-Dspring.profiles.active=k8s", "-cp", "/app/resources:/app/classes:/app/libs/*", "com.公司.部门.user.MywebUserApplication"]
   ....

改好之后 kubectl apply 重新部署即可

这里是 kubectl exec 进入 pod ,pod 中的目录,存放了 jar包 的 source,类,和依赖的 jar 包
/app/resources:/app/classes:/app/libs/*

idea 中配置监听

debug java 远程 java远程debug原理_java_02


注意host 是 监听的服务的 ip,在 k8s 项目中那就是 该项目 pod 的 ipport 是上一步服务器中项目启动 设置的监听端口

服务器上jar包运行

如果是 docker 部署的,可以 docker save -o registry.xxx.com/xxx/jar包 ,在服务器上保存一个 项目 jar 包,运行起来

pom.yml 配置

pom.xml里配置jvmArguments参数

-Xdebug -Xrunjdwp:transport=dt_socket,address=5005,server=y,suspend=n:
<build>
	<plugins>
		<plugin>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-maven-plugin</artifactId>
			<configuration>
				<jvmArguments>-Xdebug -Xrunjdwp:transport=dt_socket,address=5005,server=y,suspend=n</jvmArguments>
			</configuration>
		</plugin>
	</plugins>
</build>

加了此配置后,打包后的项目发布服务器,可支持远程DEBUG;

具体参数详解:

-Xdebug 通知JVM工作在DEBUG模式下;

-Xrunjdwp 通知JVM使用(Java debug wire protocol)运行调试环境。该参数同时包含了一系列的调试选项;

transport  指定了调试数据的传送方式,dt_socket是指用SOCKET模式,另有dt_shmem指用共享内存方式,其中,dt_shmem只适用于Windows平台;

address 调试服务器的端口号,客户端用来连接服务器的端口号;

server=y/n VM 是否需要作为调试服务器执行;

suspend=y/n 是否在调试客户端建立连接之后启动 VM;

IDEA打包jar

右侧Maven工具,双击 package打包工具;

一般打包跳过test,可以点击箭头所指闪电图标,这样打包速度会快很多

debug java 远程 java远程debug原理_JVM_03


打包后,在target目录下,会生成一个jar包;我们把它复制出来即可

debug java 远程 java远程debug原理_intellij-idea_04

启动jar并且带启动参数支持远程调试

远程 DEBUG 模式启动 jar

java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005 -jar remote-debug-v1.0.jar

启动OK,监听socket 5005端口

debug java 远程 java远程debug原理_JVM_05

IDEA远程DEBUG配置

debug java 远程 java远程debug原理_JVM_06


测试成功

debug java 远程 java远程debug原理_java_07