問題描述:
本地idea里的一個(gè)簡單java例子,debug停在圖示語句,運(yùn)行jconsole嘗試連接該進(jìn)程。反復(fù)提示連接失敗


問題診斷:
- 搜索關(guān)鍵詞“idea jconsole 本地連接失敗”,查到的都是說要在jvm參數(shù)里增加:
-Djava.net.preferIPv4Stack=true
如下圖所示增加后不生效:

- 嘗試用jconsole連接idea的進(jìn)程,可以成功:

抓出兩個(gè)進(jìn)程啟動(dòng)的參數(shù)分別如下:
【可以連接】

【不能連接】

發(fā)現(xiàn)其中不能連接的啟動(dòng)參數(shù)中有
-agentlib:jdwp=transport=dt_socket,address=127.0.0.1:58329
這是debug模式運(yùn)行時(shí)開放的端口,用于和jvm通信,獲取jvm運(yùn)行狀態(tài)中的必要信息。
于是猜想,是否是debug模式不支持連接jconsole,隨即將代碼改成如下:
public class ReferenceTest {
public static void main(String[] args){
String b = new String("test");
while(true){
System.out.println(b);
}
}
}
運(yùn)行,再從jconsole連接,成功:

- 嘗試把之前加的jvm參數(shù)都去掉,再執(zhí)行,仍然可以連接成功。
結(jié)論
idea中debug模式運(yùn)行停在斷點(diǎn)時(shí),jconsole不能連接該進(jìn)程。與jvm參數(shù)之類的沒有關(guān)系。
以上jvm參數(shù)在jconsole連接遠(yuǎn)程虛擬機(jī)進(jìn)程時(shí)需要確保設(shè)置,才能正常連接。
com.sun.management.jmxremote.port=portNum
深入探究
- debug原理:
本質(zhì)上debug原理是通過一種方式把jvm運(yùn)行時(shí)的狀態(tài)(變量值,當(dāng)前運(yùn)行行號(hào),異常信息等等)傳遞回IDE進(jìn)行顯示。這種方式不能污染jvm運(yùn)行時(shí)的數(shù)據(jù),也就是需要在運(yùn)行中途停得下來,又不會(huì)影響其繼續(xù)執(zhí)行??梢灶惐瘸伤鳎琷vm運(yùn)行時(shí)就像是水一直在流,斷點(diǎn)相當(dāng)于在水流經(jīng)的某一處放置檔板,使其完全停在此處,一旦檔板放開,水流繼續(xù)正常流淌。
具體的實(shí)現(xiàn)是基于Java對(duì)外提供的專門用于調(diào)度和監(jiān)控虛擬機(jī)使用的API,也就是Java Platform Debugger Architecture(JPDA).
關(guān)于JPDA需要知道的重點(diǎn)如下:
-
JPDA包括三個(gè)層次,圖示如下。
image.png 通過JDI與被調(diào)試的虛擬機(jī)進(jìn)程通信,底層是通過TCP socket方式實(shí)現(xiàn)的。
更多詳細(xì)說明,參考如下文檔:
https://yq.aliyun.com/articles/56?spm=5176.100238.yqhn2.7.NLnzoh
- jconsole連接原理:
底層通過jmx協(xié)議來連接、監(jiān)控和管理虛擬機(jī)進(jìn)程。
jmx協(xié)議實(shí)現(xiàn)時(shí)可以支持多種底層網(wǎng)絡(luò)協(xié)議如rmi,http等
至此,還是沒有想清楚 為什么idea中debug模式啟動(dòng)的進(jìn)程不能被jconsole連接。
進(jìn)一步查看運(yùn)行模式和debug模式啟動(dòng)進(jìn)程的差別:
運(yùn)行模式:
-javaagent:/Applications/IntelliJ IDEA.app/Contents/lib/idea_rt.jar=56196:/Applications/IntelliJ IDEA.app/Contents/bin
debug模式:
-javaagent:/Users/mac/Library/Caches/IntelliJIdea2018.2/captureAgent/debugger-agent.jar=file:/private/var/folders/58/kbmn4r191jggdg23jnph_q4c0000gn/T/capture.props
- -javaagent實(shí)際上是jvm提供的一個(gè)類似AOP的方式,允許程序運(yùn)行之前,修改運(yùn)行的字節(jié)碼。就是在運(yùn)行main函數(shù)之前,jvm會(huì)先調(diào)用javaagent里指定的一個(gè)類似interceptor的程序。相當(dāng)于開了一個(gè)proxy或者是agent。
關(guān)于javaagent的使用詳見:
https://www.cnblogs.com/aspirant/p/8796974.html
這兩種模式主要差別在于這個(gè)javaagent是不同的。
未完待續(xù):
除了這個(gè)不同以外,未發(fā)現(xiàn)其他不同。
而這個(gè)不同與jmx連接也沒啥關(guān)系。
暫時(shí)沒有其他調(diào)查思路。
