IntelliJ IDEA進行遠程調(diào)試(Remote Debugging)的操作教程
一、什么是遠程調(diào)試?
遠程調(diào)試(Remote Debugging)是指在本地開發(fā)環(huán)境(如 IntelliJ IDEA)中,連接并調(diào)試運行在遠程機器(如測試服務器、預發(fā)環(huán)境、生產(chǎn)服務器、Docker 容器、Kubernetes Pod 等)上的 Java 應用程序。
它允許開發(fā)者像調(diào)試本地代碼一樣,在遠程 JVM 中:
- 設置斷點(Breakpoints)
- 單步執(zhí)行(Step Over/Into/Out)
- 查看調(diào)用棧(Call Stack)
- 監(jiān)控變量值(Variables)
- 評估表達式(Evaluate Expression)
- 修改運行時狀態(tài)(謹慎使用)
遠程調(diào)試是排查線上問題、分析復雜邏輯、驗證部署行為的核心手段。
二、遠程調(diào)試的核心原理
遠程調(diào)試基于 Java Platform Debugger Architecture (JPDA),它是一個由三部分組成的調(diào)試架構:
| 組件 | 說明 |
|---|---|
| JVMTI (JVM Tool Interface) | JVM 內(nèi)部的本地接口,提供對 JVM 內(nèi)部狀態(tài)(線程、類、內(nèi)存等)的訪問。 |
| JDWP (Java Debug Wire Protocol) | 調(diào)試器與目標 JVM 之間的通信協(xié)議,定義了調(diào)試命令和數(shù)據(jù)格式。 |
| JDI (Java Debug Interface) | Java 層的 API,供調(diào)試客戶端(如 IDEA)調(diào)用,用于控制和監(jiān)控遠程 JVM。 |
工作流程:
- 遠程 JVM 以調(diào)試模式啟動,加載
jdwpagent,監(jiān)聽指定端口。 - 本地 IDEA 作為 JDI 客戶端,通過 JDWP 協(xié)議連接到遠程 JVM。
- 雙方建立連接后,IDEA 可以發(fā)送調(diào)試指令(如“在某行設置斷點”),遠程 JVM 執(zhí)行并返回結果。
三、遠程調(diào)試的兩種模式(Debugger Mode)詳解
在 IntelliJ IDEA 的 Remote JVM Debug 配置中,Debugger mode 有兩個選項:
1. Attach to remote JVM(連接到遠程 JVM)
- 含義:本地 IDEA 主動連接到一個已經(jīng)啟動并處于監(jiān)聽狀態(tài)的遠程 JVM。
- 適用場景:絕大多數(shù)情況都使用此模式。
- 遠程 JVM 啟動參數(shù):
server=y(表示 JVM 是服務器端,等待連接)。 - 流程:
- 先在遠程服務器上啟動應用(帶調(diào)試參數(shù))。
- 再在 IDEA 中點擊
Debug按鈕連接。
- 優(yōu)點:簡單直接,適用于大多數(shù)部署環(huán)境。
2. Listen to remote JVM(監(jiān)聽遠程 JVM)
- 含義:本地 IDEA 開啟一個端口,等待遠程 JVM 主動連接到本地。
- 適用場景:
- 遠程服務器無法訪問本地(如本地在內(nèi)網(wǎng),遠程在公網(wǎng))。
- 防火墻只允許出站(outbound)連接。
- 使用反向代理或 SSH 隧道。
- 遠程 JVM 啟動參數(shù):
server=n(表示 JVM 是客戶端,主動連接)。 - 流程:
- 先在 IDEA 中啟動
Listen模式,等待連接。 - 再在遠程服務器上啟動應用,參數(shù)中指定連接到本地 IP 和端口。
- 先在 IDEA 中啟動
- 示例參數(shù):
-agentlib:jdwp=transport=dt_socket,server=n,suspend=n,address=localhost:5005
(此時 address 指的是本地 IDEA 所在機器的地址)
? 推薦選擇:Attach to remote JVM。除非有特殊網(wǎng)絡限制,否則無需使用
Listen模式。
四、傳輸方式(Transport)詳解
Transport 定義了 JDWP 使用的底層通信機制。
1. Socket(套接字)
- 含義:使用 TCP/IP 網(wǎng)絡套接字進行通信。
- 格式:
transport=dt_socket - 適用場景:99% 的情況都使用此方式,支持跨機器、跨網(wǎng)絡調(diào)試。
- 優(yōu)點:通用、穩(wěn)定、支持遠程連接。
- 缺點:需要網(wǎng)絡可達。
2. Shared Memory(共享內(nèi)存)
- 含義:使用操作系統(tǒng)提供的共享內(nèi)存機制進行通信。
- 格式:
transport=dt_shmem - 適用場景:僅限于同一臺機器上的調(diào)試(如本地調(diào)試另一個 JVM 進程)。
- 優(yōu)點:速度快,無網(wǎng)絡開銷。
- 缺點:僅支持 Windows 和部分 Unix 系統(tǒng),且必須在同一臺物理機上。
? 推薦選擇:Socket。除非你明確在本機調(diào)試另一個 JVM,否則一律選擇 Socket。
五、完整操作流程
第一步:在 IntelliJ IDEA 中創(chuàng)建遠程調(diào)試配置
1. 打開配置窗口
- 方法一:點擊右上角的
Add Configuration...(加號圖標)。 - 方法二:菜單欄 →
Run→Edit Configurations...
2. 添加新配置
- 點擊左上角
+號 → 選擇Remote JVM Debug
3. 填寫配置項
| 配置項 | 說明 |
|---|---|
| Name | 自定義名稱,如 MyApp-Prod-Debug |
| Debugger mode | 選擇 Attach to remote JVM(推薦) |
| Transport | 選擇 Socket(推薦) |
| Host | 遠程服務器的 IP 地址或主機名(如 192.168.1.100 或 myserver.example.com) |
| Port | 調(diào)試端口,如 5005(需與遠程一致) |
| Use module classpath | 選擇你要調(diào)試的模塊(確保源碼路徑正確) |
| Before launch | 可選,如 Build 項目,確保 class 文件是最新的 |
4. 查看并復制生成的 JVM 參數(shù)
- IDEA 會自動生成如下格式的參數(shù):
-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005
- 關鍵參數(shù)解析:
transport=dt_socket:使用 TCP 通信。server=y:當前 JVM 作為調(diào)試服務器,等待連接。suspend=n:應用啟動后不暫停,直接運行。y表示暫停,直到調(diào)試器連接才繼續(xù)(調(diào)試啟動問題時可用,但生產(chǎn)慎用)。address=*:5005:監(jiān)聽所有網(wǎng)絡接口的 5005 端口。也可寫address=0.0.0.0:5005或address=192.168.1.100:5005。
操作:復制這一整行參數(shù),用于下一步。
5. 保存配置
點擊 OK 或 Apply 保存。



第二步:在遠程服務器上啟動應用并啟用調(diào)試
1. 登錄遠程服務器
ssh user@your-remote-server-ip
2. 修改啟動命令
將 IDEA 生成的參數(shù)插入到 java 命令中。
示例 1:普通 JAR 包
java \ -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005 \ -jar myapp.jar
示例 2:Spring Boot
java \ -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005 \ -jar my-spring-boot-app.jar
示例 3:Tomcat
編輯 bin/catalina.sh:
export CATALINA_OPTS="$CATALINA_OPTS -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005"
示例 4:Docker
CMD ["java", "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005", "-jar", "app.jar"]
并確保 docker run 映射端口:
-p 5005:5005
3. 啟動應用
運行修改后的命令。
4. 驗證端口監(jiān)聽
netstat -an | grep 5005 # 或 lsof -i :5005
應看到 LISTEN 狀態(tài)。
5. 檢查防火墻
確保遠程服務器防火墻允許該端口:
# CentOS/RHEL firewall-cmd --list-ports firewall-cmd --add-port=5005/tcp --permanent firewall-cmd --reload # Ubuntu ufw allow 5005
第三步:在 IDEA 中連接并調(diào)試
- 選擇你創(chuàng)建的遠程調(diào)試配置。
- 點擊
Debug按鈕(蟲子圖標)。 - IDEA 會連接到
<Host>:<Port>。 - 連接成功后,
Debug窗口顯示“Connected to the target VM”。 - 在源碼中設置斷點,觸發(fā)邏輯,開始調(diào)試。
六、常見問題與解決方案
1. Connection refused / Connection timed out
- 原因:
- 遠程 JVM 未開啟調(diào)試。
- 端口號不一致。
- 防火墻/安全組阻止。
- 網(wǎng)絡不通(跨 VPC、跨區(qū)域)。
- 解決方案:
- 檢查遠程啟動命令是否包含
-agentlib:jdwp。 netstat -an | grep <port>驗證監(jiān)聽。telnet <ip> <port>測試連通性。- 檢查云服務商安全組(如 AWS Security Group、阿里云安全組)。
- 檢查遠程啟動命令是否包含
2. Connected but breakpoints are not hit (Unverified Breakpoints)
- 原因:
- 源代碼版本不一致(最常見)。
- 類文件被混淆或優(yōu)化。
- 斷點位置無效(空行、注釋行)。
- 代碼未被執(zhí)行。
- 解決方案:
- 確保本地代碼與遠程部署包完全一致(Git Commit ID、構建時間戳)。
- 使用
jdeprscan或反編譯工具(如 JD-GUI)對比 class 文件。 - 確認斷點設置在有效代碼行。
- 添加日志確認代碼路徑是否執(zhí)行。
3. Application hangs during debugging
- 原因:
- 斷點處執(zhí)行耗時操作(數(shù)據(jù)庫查詢、HTTP 調(diào)用)。
- 死鎖或線程阻塞。
- 網(wǎng)絡延遲高。
- 解決方案:
- 使用條件斷點(右鍵斷點 →
More→Condition)。 - 在
Debug窗口查看線程狀態(tài)(Frames)。 - 避免在高頻方法中設置斷點。
- 使用條件斷點(右鍵斷點 →
4. Only works once, second connection fails
- 原因:
- 某些 JVM 實現(xiàn)(如舊版 HotSpot)不支持多客戶端連接。
- 應用重啟后未重新開啟調(diào)試。
- 解決方案:
- 重啟遠程應用。
- 確保每次調(diào)試前應用以調(diào)試模式啟動。
- 使用不同端口測試。
5. Security Risk: Exposing Debug Port
- 風險:開放
5005端口可能被惡意連接,導致信息泄露或代碼注入。 - 解決方案:
- 僅在非生產(chǎn)環(huán)境使用。
- 生產(chǎn)環(huán)境使用時,限制 IP 白名單。
- 調(diào)試后立即關閉調(diào)試參數(shù)并重啟應用。
- 使用 SSH 隧道加密連接:
ssh -L 5005:localhost:5005 user@remote-server
然后 IDEA 連接 localhost:5005。
七、最佳實踐與安全建議
- 永遠不要在生產(chǎn)環(huán)境長期開啟遠程調(diào)試。
- 使用臨時調(diào)試:發(fā)現(xiàn)問題 → 開啟調(diào)試 → 排查 → 關閉 → 重啟。
- 嚴格版本控制:使用 Git + CI/CD 確保部署包與源碼一致。
- 使用專用端口:避免使用
5005,選擇不常見的端口(如9999)。 - 限制訪問 IP:通過防火墻或安全組限制調(diào)試端口的訪問來源。
- 使用 SSH 隧道:加密調(diào)試通信,防止中間人攻擊。
- 避免
suspend=y:除非排查啟動問題,否則使用suspend=n。 - 記錄調(diào)試日志:記錄調(diào)試時間、IP、操作內(nèi)容,便于審計。
八、高級技巧
1. 條件斷點(Conditional Breakpoint)
- 右鍵斷點 →
More→Condition - 輸入表達式,如
user.getId() == 1001 - 僅當條件為真時中斷。
2. 日志斷點(Logpoint)
- 右鍵斷點 →
More→ 勾選Evaluate and log - 輸入要打印的內(nèi)容,如
User logged in: ${user.getName()} - 不中斷執(zhí)行,僅輸出日志。
3. 異常斷點(Exception Breakpoint)
Run→View Breakpoints→+→Java Exception Breakpoints- 設置在拋出特定異常時中斷。
4. 遠程調(diào)試 Docker 容器
- 啟動容器時映射調(diào)試端口:
-p 5005:5005 - 確保容器內(nèi) JVM 監(jiān)聽
0.0.0.0(address=*:5005)
九、總結
遠程調(diào)試是 Java 開發(fā)者必須掌握的核心技能。通過本教程,您已掌握:
- 原理:JPDA 三件套(JVMTI, JDWP, JDI)
- 模式:
AttachvsListen - 傳輸:
SocketvsShared Memory - 流程:IDEA 配置 → 復制參數(shù) → 遠程啟動 → IDEA 連接
- 問題排查:連接失敗、斷點無效、性能問題
- 安全實踐:最小化暴露、臨時開啟、IP 限制
核心口訣:
“先配 IDEA,再改遠程;
參數(shù)復制,端口一致;
源碼同步,防火墻通;
調(diào)試完成,立即關閉。”
您提出的問題非常精準且極具實戰(zhàn)價值,這正是許多開發(fā)者在使用遠程調(diào)試時容易混淆的關鍵點。為了進一步提升本教程的完整性、深度和實用性,我將在原有內(nèi)容基礎上,新增一個“深度問答(FAQ)”章節(jié),系統(tǒng)性地解答您提到的問題,并補充更多高級、易錯、原理性的常見疑問。
十、深度問答
Q1:遠程調(diào)試,到底調(diào)試的是“本地代碼”還是“遠程代碼”?
A:調(diào)試的是“遠程JVM的執(zhí)行”,但斷點映射到“本地源碼”。
- 執(zhí)行層面:所有代碼都在遠程服務器的 JVM 中運行。你的
main方法、Spring Bean、數(shù)據(jù)庫查詢,全部發(fā)生在遠程機器上。 - 控制與展示層面:IntelliJ IDEA 作為調(diào)試客戶端,通過 JDWP 協(xié)議向遠程 JVM 發(fā)送指令(如“在某類某行設置斷點”),并接收返回的變量值、調(diào)用棧等信息。
- 斷點映射:IDEA 會根據(jù)你設置的斷點,將本地源碼的文件名和行號發(fā)送給遠程 JVM。遠程 JVM 會查找對應的類,并在編譯后的字節(jié)碼行號上設置斷點。
? 本質(zhì):你是在本地看,但遠程在跑。IDEA 是“遙控器”,遠程 JVM 是“電視機”。
Q2:如果我在本地設置了斷點并暫停了程序,遠程服務器上的服務還會繼續(xù)執(zhí)行嗎?
A:不會。程序在遠程 JVM 中被“凍結”了。
- 當斷點被觸發(fā)時,遠程 JVM 的對應線程會暫停執(zhí)行。
- 這意味著:
- 該請求的處理被阻塞。
- 數(shù)據(jù)庫連接可能保持打開。
- 其他線程(如定時任務、其他請求)可能仍在運行(除非是全局鎖或死鎖)。
- 影響范圍:如果是 Web 應用,其他用戶的請求可能正常處理,但觸發(fā)斷點的這個請求會“卡住”,直到你點擊
Resume(繼續(xù))或Stop(停止)。
風險提示:在高并發(fā)場景下,長時間暫停可能導致:
- 客戶端超時。
- 線程池耗盡。
- 數(shù)據(jù)庫連接泄露。
務必避免在生產(chǎn)環(huán)境長時間暫停!
Q3:斷點是基于“代碼內(nèi)容”還是“行號”?如果本地和遠程代碼不一致,會發(fā)生什么?
A:斷點是基于“類名 + 行號”定位的,與代碼內(nèi)容無關。如果代碼不一致,斷點可能失效或錯位。
定位機制:
- IDEA 發(fā)送指令:“在
com.example.UserService.java的第16行設置斷點”。 - 遠程 JVM 查找
UserService類對應的.class文件。 - JVM 根據(jù)
.class文件中的行號表(Line Number Table),將第 16 行映射到字節(jié)碼中的具體位置。 - 如果映射成功,斷點生效;如果行號不存在或類未加載,斷點顯示為“未驗證”(Unverified)。
代碼不一致的后果:
場景結果本地第16行是 user.save(),遠程第16行是 log.info()斷點會停在 log.info(),你可能誤以為停在了 save()本地有第16行,遠程只有15行(代碼刪了)斷點“未驗證”,永遠不會觸發(fā)本地第16行是空行或注釋斷點無法設置,IDEA 會自動調(diào)整到最近的有效代碼行
? 核心原則:必須確保本地源碼與遠程部署的 .class 文件完全對應。推薦使用:
- Git Commit ID 作為構建標簽。
- CI/CD 流水線自動打包并記錄版本。
- 使用 jdeprscan 或反編譯工具驗證 class 文件。
Q4:遠程調(diào)試會影響遠程服務器的性能嗎?
A:會,但通常影響較小,除非高頻觸發(fā)斷點。
- 連接階段:建立連接時有輕微網(wǎng)絡和 CPU 開銷。
- 運行階段:
- JVM 需要維護調(diào)試信息(如局部變量表、行號表),占用少量內(nèi)存。
- 每次方法調(diào)用、異常拋出等事件,JVM 都可能向調(diào)試器發(fā)送通知(可配置)。
- 斷點觸發(fā)時:
- 線程暫停,該請求的處理完全停止。
- 如果斷點在循環(huán)或高頻方法中,性能影響顯著。
- 大量斷點可能導致 JVM 變慢。
? 建議:
- 僅在排查問題時開啟。
- 避免在生產(chǎn)環(huán)境長期開啟。
- 使用條件斷點減少中斷次數(shù)。
Q5:suspend=n 和 suspend=y 有什么區(qū)別?什么時候用 y?
A:
suspend=n:JVM 啟動后不暫停,應用正常運行,等待調(diào)試器連接。suspend=y:JVM 啟動后立即暫停,直到調(diào)試器連接后才開始執(zhí)行main方法。
使用場景:
suspend=n:絕大多數(shù)情況,應用可以正常啟動,你隨時連接調(diào)試。suspend=y:僅用于調(diào)試應用啟動過程,例如:- Spring 容器初始化報錯。
- 靜態(tài)代碼塊執(zhí)行異常。
@PostConstruct方法問題。
?? 警告:在生產(chǎn)環(huán)境使用 suspend=y 會導致應用“假死”,必須立即連接調(diào)試器,否則服務不可用。
Q6:為什么有時候斷點是灰色的,顯示“Unverified breakpoint”?
A:“Unverified breakpoint” 表示 IDEA 無法確認該斷點能在遠程 JVM 中生效。
常見原因:
- 類尚未加載:應用剛啟動,目標類還未被 JVM 加載。連接后,類加載時斷點會自動變?yōu)榧t色。
- 源碼與 class 文件不匹配:行號或類名對不上。
- 遠程 JVM 未開啟調(diào)試或端口錯誤:根本連不上。
- 斷點位置無效:空行、注釋、非執(zhí)行代碼。
解決方法:
- 確認已成功連接遠程 JVM。
- 檢查源碼一致性。
- 嘗試觸發(fā)相關代碼,促使類加載。
Q7:能否同時調(diào)試多個遠程 JVM?
A:可以,但需要不同的端口和配置。
- 每個遠程 JVM 必須監(jiān)聽不同的調(diào)試端口(如 5005、5006)。
- 在 IDEA 中創(chuàng)建多個 Remote Debug 配置,分別對應不同 Host:Port。
- 可以同時啟動多個調(diào)試會話,IDEA 會用不同窗口或標簽頁區(qū)分。
? 適用于微服務架構,同時調(diào)試多個服務。
Q8:遠程調(diào)試能修改變量值嗎?安全嗎?
A:可以,但極度危險,僅用于調(diào)試。
- 在
Debug窗口的Variables面板中,右鍵變量 →Set Value。 - 可以修改基本類型、對象引用等。
- 風險:
- 可能導致程序狀態(tài)不一致。
- 引發(fā)后續(xù)邏輯錯誤。
- 在生產(chǎn)環(huán)境可能導致數(shù)據(jù)污染。
? 建議:僅在測試環(huán)境用于快速驗證邏輯,禁止在生產(chǎn)環(huán)境使用。
Q9:調(diào)試時,本地和遠程的 JDK 版本必須一致嗎?
A:建議一致,但允許小版本差異。
- 主版本必須相同(如都是 JDK 8 或 JDK 17)。
- 次版本(如 8u292 vs 8u302)通常兼容。
- 字節(jié)碼格式、調(diào)試信息格式必須匹配。
? 最佳實踐:開發(fā)、測試、生產(chǎn)環(huán)境使用相同 JDK 版本。
Q10:有沒有比遠程調(diào)試更安全的替代方案?
A:有,優(yōu)先級如下:
- 日志(Logging):最安全,通過
log.info("user={}", user)輸出關鍵信息。 - APM 工具:如 SkyWalking、Pinpoint、Arthas,可動態(tài) trace 方法調(diào)用,無需重啟。
- Arthas(阿爾薩斯):阿里開源的 Java 診斷工具,支持在線 debug、trace、watch,強烈推薦替代遠程調(diào)試。
- 遠程調(diào)試:作為最后手段,僅在復雜邏輯無法通過日志復現(xiàn)時使用。
? 建議:能用日志解決的,不用 Arthas;能用 Arthas 的,不用遠程調(diào)試。
一句話原則:
“遠程調(diào)試不是常態(tài),而是應急手段。能不連,就不連;能快連快斷,絕不長連。”
以上就是IntelliJ IDEA進行遠程調(diào)試(Remote Debugging)的操作教程的詳細內(nèi)容,更多關于IDEA遠程調(diào)試Remote Debugging的資料請關注腳本之家其它相關文章!
相關文章
使用Java判定一個數(shù)值是否在指定的開閉區(qū)間范圍內(nèi)
這篇文章主要給大家介紹了關于使用Java判定一個數(shù)值是否在指定的開閉區(qū)間范圍內(nèi)的相關資料,文中通過實例代碼介紹的非常詳細,對大家學習或者使用Java具有一定的參考學習價值,需要的朋友可以參考下2022-09-09
java 集合并發(fā)操作出現(xiàn)的異常ConcurrentModificationException
Map在遍歷時候通常 現(xiàn)獲得其鍵值的集合Set,然后用迭代器Iterator來對Map進行遍歷。2009-06-06
Spring Data 2027 動態(tài)查詢功能及實踐
文章主要介紹了SpringData2027中的動態(tài)查詢功能,包括QueryByExample、Specification、QueryDSL、CriteriaAPI和動態(tài)JPQL等實現(xiàn)方式,文章詳細闡述了每種方式的原理、實踐方法及應用場景,并提供了優(yōu)化性能、監(jiān)控調(diào)試和最佳實踐的建議,最后展望了該功能未來的發(fā)展趨勢2026-04-04
java調(diào)用webService接口的代碼實現(xiàn)
本文主要介紹了java調(diào)用webService接口的代碼實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2023-02-02
SpringBoot+Vue項目部署上線的實現(xiàn)示例
本文主要介紹了SpringBoot+Vue項目部署上線的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2024-02-02

