成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

JVM源碼分析之Attach機(jī)制實(shí)現(xiàn)完全解讀

開(kāi)發(fā) 后端
那Attach機(jī)制是什么?說(shuō)簡(jiǎn)單點(diǎn)就是jvm提供一種jvm進(jìn)程間通信的能力,能讓一個(gè)進(jìn)程傳命令給另外一個(gè)進(jìn)程,并讓它執(zhí)行內(nèi)部的一些操作。

Attach是什么

在講這個(gè)之前,我們先來(lái)點(diǎn)大家都知道的東西,當(dāng)我們感覺(jué)線程一直卡在某個(gè)地方,想知道卡在哪里,首先想到的是進(jìn)行線程dump,而常用的命令是jstack ,我們就可以看到如下線程棧了

大家是否注意過(guò)上面圈起來(lái)的兩個(gè)線程,”Attach Listener”和“Signal Dispatcher”,這兩個(gè)線程是我們這次要講的Attach機(jī)制的關(guān)鍵,先偷偷告訴各位,其實(shí)Attach Listener這個(gè)線程在jvm起來(lái)的時(shí)候可能并沒(méi)有的,后面會(huì)細(xì)說(shuō)。

那Attach機(jī)制是什么?說(shuō)簡(jiǎn)單點(diǎn)就是jvm提供一種jvm進(jìn)程間通信的能力,能讓一個(gè)進(jìn)程傳命令給另外一個(gè)進(jìn)程,并讓它執(zhí)行內(nèi)部的一些操作,比如說(shuō)我們?yōu)榱俗屃硗庖粋€(gè)jvm進(jìn)程把線程dump出來(lái),那么我們跑了一個(gè)jstack的進(jìn)程,然后傳了個(gè)pid的參數(shù),告訴它要哪個(gè)進(jìn)程進(jìn)行線程dump,既然是兩個(gè)進(jìn)程,那肯定涉及到進(jìn)程間通信,以及傳輸協(xié)議的定義,比如要執(zhí)行什么操作,傳了什么參數(shù)等

Attach能做些什么

總結(jié)起來(lái)說(shuō),比如內(nèi)存dump,線程dump,類信息統(tǒng)計(jì)(比如加載的類及大小以及實(shí)例個(gè)數(shù)等),動(dòng)態(tài)加載agent(使用過(guò)btrace的應(yīng)該不陌生),動(dòng)態(tài)設(shè)置vm flag(但是并不是所有的flag都可以設(shè)置的,因?yàn)橛行ゝlag是在jvm啟動(dòng)過(guò)程中使用的,是一次性的),打印vm flag,獲取系統(tǒng)屬性等,這些對(duì)應(yīng)的源碼(AttachListener.cpp)如下 

  1. static AttachOperationFunctionInfo funcs[] = {  
  2.   { "agentProperties",  get_agent_properties },  
  3.   { "datadump",         data_dump },  
  4.   { "dumpheap",         dump_heap },  
  5.   { "load",             JvmtiExport::load_agent_library },  
  6.   { "properties",       get_system_properties },  
  7.   { "threaddump",       thread_dump },  
  8.   { "inspectheap",      heap_inspection },  
  9.   { "setflag",          set_flag },  
  10.   { "printflag",        print_flag },  
  11.   { "jcmd",             jcmd },  
  12.   { NULL,               NULL }  
  13. }; 

后面是命令對(duì)應(yīng)的處理函數(shù)。

Attach在jvm里如何實(shí)現(xiàn)的

Attach Listener線程的創(chuàng)建

前面也提到了,jvm在啟動(dòng)過(guò)程中可能并沒(méi)有啟動(dòng)Attach Listener這個(gè)線程,可以通過(guò)jvm參數(shù)來(lái)啟動(dòng),代碼 (Threads::create_vm)如下: 

  1. if (!DisableAttachMechanism) {  
  2.    if (StartAttachListener || AttachListener::init_at_startup()) {  
  3.      AttachListener::init();  
  4.    }  
  5.  }  
  6. ool AttachListener::init_at_startup() {  
  7.  if (ReduceSignalUsage) {  
  8.    return true;  
  9.  } else {  
  10.    return false;  
  11.  } 

其中DisableAttachMechanism,StartAttachListener ,ReduceSignalUsage均默認(rèn)是false(globals.hpp) 

  1. product(bool, DisableAttachMechanism, false,                         
  2.           "Disable mechanism that allows tools to Attach to this VM”)     
  3. product(bool, StartAttachListener, false,                                
  4.            "Always start Attach Listener at VM startup")    
  5. product(bool, ReduceSignalUsage, false,                                    
  6.            "Reduce the use of OS signals in Java and/or the VM”) 

因此AttachListener::init()并不會(huì)被執(zhí)行,而Attach Listener線程正是在此方法里創(chuàng)建的

既然在啟動(dòng)的時(shí)候不會(huì)創(chuàng)建這個(gè)線程,那么我們?cè)谏厦婵吹降哪莻€(gè)線程是怎么創(chuàng)建的呢,這個(gè)就要關(guān)注另外一個(gè)線程“Signal Dispatcher”了,顧名思義是處理信號(hào)的,這個(gè)線程是在jvm啟動(dòng)的時(shí)候就會(huì)創(chuàng)建的,具體代碼就不說(shuō)了。

下面以jstack的實(shí)現(xiàn)來(lái)說(shuō)明觸發(fā)Attach這一機(jī)制進(jìn)行的過(guò)程,jstack命令的實(shí)現(xiàn)其實(shí)是一個(gè)叫做JStack.java的類,查看jstack代碼后會(huì)走到下面的方法里

請(qǐng)注意VirtualMachine.Attach(pid);這行代碼,觸發(fā)Attach pid的關(guān)鍵,如果是在linux下會(huì)走到下面的構(gòu)造函數(shù)

這里要解釋下代碼了,首先看到調(diào)用了createAttachFile方法在目標(biāo)進(jìn)程的cwd目錄下創(chuàng)建了一個(gè)文件/proc//cwd/.Attach_pid,這個(gè)在后面的信號(hào)處理過(guò)程中會(huì)取出來(lái)做判斷(為了安全),另外我們知道在linux下線程是用進(jìn)程實(shí)現(xiàn)的,在jvm啟動(dòng)過(guò)程中會(huì)創(chuàng)建很多線程,比如我們上面的信號(hào)線程,也就是會(huì)看到很多的pid(應(yīng)該是LWP),那么如何找到這個(gè)信號(hào)處理線程呢,從上面實(shí)現(xiàn)來(lái)看是找到我們傳進(jìn)去的pid的父進(jìn)程,然后給它的所有子進(jìn)程都發(fā)送一個(gè)SIGQUIT信號(hào),而jvm里除了信號(hào)線程,其他線程都設(shè)置了對(duì)此信號(hào)的屏蔽,因此收不到該信號(hào),于是該信號(hào)就傳給了“Signal Dispatcher”,在傳完之后作輪詢等待看目標(biāo)進(jìn)程是否創(chuàng)建了某個(gè)文件,AttachTimeout默認(rèn)超時(shí)時(shí)間是5000ms,可通過(guò)設(shè)置系統(tǒng)變量sun.tools.Attach.AttachTimeout來(lái)指定,下面是Signal Dispatcher線程的entry實(shí)現(xiàn)

當(dāng)信號(hào)是SIGBREAK(在jvm里做了#define,其實(shí)就是SIGQUIT)的時(shí)候,就會(huì)觸發(fā)

AttachListener::is_init_trigger()的執(zhí)行

一開(kāi)始會(huì)判斷當(dāng)前進(jìn)程目錄下是否有個(gè).Attach_pid文件(前面提到了),如果沒(méi)有就會(huì)在/tmp下創(chuàng)建一個(gè)/tmp/.Attach_pid,當(dāng)那個(gè)文件的uid和自己的uid是一致的情況下(為了安全)再調(diào)用init方法

此時(shí)水落石出了,看到創(chuàng)建了一個(gè)線程,并且取名為Attach Listener。再看看其子類LinuxAttachListener的init方法

看到其創(chuàng)建了一個(gè)監(jiān)聽(tīng)套接字,并創(chuàng)建了一個(gè)文件/tmp/.java_pid,這個(gè)文件就是客戶端之前一直在輪詢等待的文件,隨著這個(gè)文件的生成,意味著Attach的過(guò)程圓滿結(jié)束了。

Attach listener接收請(qǐng)求

看看它的entry實(shí)現(xiàn)Attach_listener_thread_entry

從代碼來(lái)看就是從隊(duì)列里不斷取AttachOperation,然后找到請(qǐng)求命令對(duì)應(yīng)的方法進(jìn)行執(zhí)行,比如我們一開(kāi)始說(shuō)的jstack命令,找到 { “threaddump”, thread_dump }的映射關(guān)系,然后執(zhí)行thread_dump方法

再來(lái)看看其要調(diào)用的AttachListener::dequeue(), 

  1. AttachOperation* AttachListener::dequeue() {  
  2.   JavaThread* thread = JavaThread::current();  
  3.   ThreadBlockInVM tbivm(thread);  
  4.   thread->set_suspend_equivalent();  
  5.   // cleared by handle_special_suspend_equivalent_condition() or  
  6.   // java_suspend_self() via check_and_wait_while_suspended()  
  7.   AttachOperation* op = LinuxAttachListener::dequeue();  
  8.   // were we externally suspended while we were waiting?  
  9.   thread->check_and_wait_while_suspended();  
  10.   return op;  

最終調(diào)用的是LinuxAttachListener::dequeue(),

我們看到如果沒(méi)有請(qǐng)求的話,會(huì)一直accept在那里,當(dāng)來(lái)了請(qǐng)求,然后就會(huì)創(chuàng)建一個(gè)套接字,并讀取數(shù)據(jù),構(gòu)建出LinuxAttachOperation返回并執(zhí)行。

整個(gè)過(guò)程就這樣了,從Attach線程創(chuàng)建到接收請(qǐng)求,處理請(qǐng)求。 

 

責(zé)任編輯:龐桂玉 來(lái)源: segmentfault
相關(guān)推薦

2017-01-12 14:52:03

JVMFinalRefere源碼

2017-01-11 14:02:32

JVM源碼內(nèi)存

2017-01-11 14:19:26

JVM源碼All

2010-09-26 16:55:31

JVM學(xué)習(xí)筆記

2023-10-31 16:00:51

類加載機(jī)制Java

2024-09-06 09:37:45

WebApp類加載器Web 應(yīng)用

2017-02-27 11:48:58

JVM源碼分析Java

2021-11-11 17:40:08

WatchdogAndroid源碼分析

2020-07-21 14:19:18

JVM編程語(yǔ)言

2022-05-19 07:09:29

機(jī)制沙箱安全JVM

2024-10-31 09:24:42

2021-03-11 08:10:48

JVM對(duì)象的創(chuàng)建School

2017-01-11 22:51:39

2011-06-23 13:10:39

Python 對(duì)象機(jī)制

2011-05-26 10:05:48

MongoDB

2022-07-19 20:04:31

NAPI模塊鴻蒙

2022-09-23 08:02:42

Kafka消息緩存

2010-09-27 10:30:42

JVM對(duì)象生命周期

2012-05-31 02:54:07

HadoopJava

2010-09-26 16:14:22

JVM實(shí)現(xiàn)機(jī)制JVM
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 欧美一区二区三区精品 | 一级毛片视频在线观看 | 成人免费看片又大又黄 | 亚洲 欧美 日韩 在线 | 精品久久久一区 | 中文字幕国产精品 | 黄色av免费网站 | 亚洲一区二区中文字幕 | 国产精品高清在线 | 日本特黄特色aaa大片免费 | 天天艹天天干天天 | 精品欧美色视频网站在线观看 | 亚洲精品18 | 91精品久久久久久久久久小网站 | 精品视频99| 北条麻妃av一区二区三区 | 国产高清久久 | 国产最新视频在线 | 福利成人| 欧美a免费| 免费视频一区二区 | 国产一区二区日韩 | 黄色大片毛片 | 香蕉久久av | 成人久久网| 亚洲国产欧美在线人成 | 波多野结衣在线观看一区二区三区 | 日韩在线免费 | 狠狠av| 国产欧美日韩久久久 | 久久男人天堂 | 欧美成人高清 | 亚洲欧美第一视频 | 国产www. | 中文字幕国产一区 | 天天艹日日干 | 欧美亚洲一区二区三区 | 国产又色又爽又黄又免费 | 久久免费资源 | 国产精品国产三级国产播12软件 | 伊人网伊人网 |