1. 程式人生 > >遠端debug除錯java程式碼

遠端debug除錯java程式碼

該系列介紹一些java開發中常用的一些小技巧,多小呢,從不會到會只需要一篇文章這麼小。這一篇介紹如何使用jdk自帶的擴充套件包配合Intellij IDEA實現遠端debug。

專案中經常會有出現這樣的問題,會令程式設計師抓狂:關鍵程式碼段沒有列印日誌,本地環境正常生產環境卻又問題…這時候,遠端debug可能會啟動作用。

1 準備用於debug的程式碼

準備一個RestController用於接收請求,最後可以通過本地斷點驗證是否成功開啟了遠端debug

1

2

3

4

5

6

7

8

9

10

11

12

13

@RestController

public class TestController {

@RequestMapping("/test")

public Integer test() {

int i = 0;

i++;

i++;

i++;

i++;

i++;

return i;

}

}

專案使用springboot和maven構建,依賴就省略了,使用springboot提供的maven打包外掛,方便我們打包成可執行的jar。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

<build>

<plugins>

<plugin>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-maven-plugin</artifactId>

<configuration>

<executable>true</executable>

</configuration>

</plugin>

<plugin>

<artifactId>maven-compiler-plugin</artifactId>

<configuration>

<source>1.8</source>

<target>1.8</target>

</configuration>

</plugin>

</plugins>

</build>

2 使用maven外掛打包成jar

3 準備啟動指令碼

1

java -jar -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=64057 remote-debug-1.0-SNAPSHOT.jar

  1. 使用java -jar的方式啟動程式,並且添加了一串特殊的引數,這是我們能夠開啟遠端debug的關鍵,以-開頭的引數是jvm的標準啟動引數,關於jvm啟動引數相關的知識可以先去其他部落格瞭解。
  2. -agentlib:libname[=options], 用於裝載本地lib包。在這條指令中便是載入了jdwp(Java Debug Wire Protocol)這個用於遠端除錯java的擴充套件包。而transport=dt_socket,server=y,suspend=n,address=64057這些便是jdwp裝載時的定製引數,詳細的引數作用可以搜尋jdwp進行了解。我們需要關心的只有address=64057這個引數選項,本地除錯程式使用64057埠與其通訊,從而遠端除錯。

4 配置IDEA

  1. 與指令碼中的指令完全一致
  2. 遠端jar包執行的host,由於我的jar執行在本地,所以使用的是localhost,一般線上環境自然是修改為線上的地址
  3. 與遠端jar包進行互動的埠號,idea會根據指令自動幫我們輸入
  4. 選擇與遠端jar包一致的原生代碼

請務必保證遠端jar包的程式碼與原生代碼一致!!!

5 驗證

儲存第4步的配置後,先執行指令碼讓遠端的jar包跑起來,再在IDEA中執行remote-debug

如上便代表連線執行成功了

在本地打上斷點,訪問localhost:8080/test

可以在本地看到堆疊資訊,大功告成。一行指令便完成了遠端除錯。

遠端除錯

遠端除錯分為主動連線除錯,和被動連線除錯。這裡以Eclipse為例。

主動連線除錯:服務端配置監控埠,本地IDE連線遠端監聽埠進行除錯,一般除錯問題用這種方式。

被動連線除錯:本地IDE監聽某埠,等待遠端連線本地埠。一般用於遠端服務啟動不了,啟動時連線到本地除錯分析。

主動連線除錯

首先需要遠端服務配置啟動指令碼:

JAVA_OPTS="$JAVA_OPTS -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8000"

如果是啟動jar包,指令:

java -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8000 -jar test.jar  

這裡-Xdebug是通知JVM工作在DEBUG模式下,-Xrunjdwp是通知JVM使用(java debug wire protocol)來執行除錯環境。transport是監聽Socket埠連線方式(也可以dt_shmem共享記憶體方式,但限於windows機器,並且服務提供端和除錯端只能位於同一臺機)。server=y表示當前是除錯服務端,=n表示當前是除錯客戶端。suspend=n表示啟動時不中斷(如果啟動時中斷,一般用於除錯啟動不了的問題)。address=8000表示本地監聽8000埠。

遠端服務(tomcat/jboss)啟動成功後,本地Eclipse對需要除錯的地方打上斷點,然後專案右鍵啟動遠端除錯:Debug as->Debug Configurations->Remote Java Application。Host為遠端主機IP,Port為遠端監聽除錯埠,Connection Type為:Standard(Socket Attach),如圖:

點選Debug,然後打斷點,遠端服務執行到斷點處本地就會中斷,然後進行除錯。

被動連線除錯

首先需要Eclipse配置監聽,如主動連線除錯的Eclipse配置圖片,Connection Type選擇:Standard(Socket Listen),配置本地監聽埠,比如預設8000。點選Debug開始等待遠端連線除錯。

然後配置遠端服務啟動指令碼:

JAVA_OPTS="$JAVA_OPTS -Xdebug -Xrunjdwp:transport=dt_socket,address=127.0.0.1:8000,suspend=y"

如果是除錯jar包,指令:

java -Xdebug -Xrunjdwp:transport=dt_socket,address=127.0.0.1:8000,suspend=y -jar remoting-debug.jar

引數含義和主動連線除錯一樣,只是這裡suspend=y表示啟動時就中斷,需要連線本地IDE除錯啟動。address=ip:port,ip需要修改為本地的對外IP。

這樣遠端專案啟動時就連線到本地,方便除錯專案啟動不了的問題。

更多引數細節:

-XDebug               啟用除錯。
-Xnoagent             禁用預設sun.tools.debug偵錯程式。
-Djava.compiler=NONE  禁止 JIT 編譯器的載入。
-Xrunjdwp             載入JDWP的JPDA參考執行例項。
transport             用於在除錯程式和 VM 使用的程序之間通訊。
dt_socket             套接字傳輸。
dt_shmem              共享記憶體傳輸,僅限於 Windows。
server=y/n            VM 是否需要作為除錯伺服器執行。
address=3999          除錯伺服器的埠號,客戶端用來連線伺服器的埠號。
suspend=y/n           是否在除錯客戶端建立連線之後啟動 VM 。