您好,登錄后才能下訂單哦!
這篇文章主要介紹“SafePoint安全點(diǎn)是什么”,在日常操作中,相信很多人在SafePoint安全點(diǎn)是什么問(wèn)題上存在疑惑,小編查閱了各式資料,整理出簡(jiǎn)單好用的操作方法,希望對(duì)大家解答”SafePoint安全點(diǎn)是什么”的疑惑有所幫助!接下來(lái),請(qǐng)跟著小編一起來(lái)學(xué)習(xí)吧!
safepoint又稱為安全點(diǎn),它是hotspot等JVM中的一個(gè)重要概念。下面我們分部分了解下safepoint是什么、safepoint的作用、safepoint是如何實(shí)現(xiàn)的以及作為開(kāi)發(fā)者有哪些需要注意的地方。
JVM的主要任務(wù)是執(zhí)行Java程序,而JVM運(yùn)行時(shí)本身也是一個(gè)程序,但是為了執(zhí)行Java程序JVM還有不少輔助工作,比如進(jìn)行GC、JIT編譯等等。一般會(huì)把運(yùn)行在JVM上的用戶Java程序稱為mutator。
GC為例,JVM中一般的GC都使用可達(dá)性分析,也就是從應(yīng)用程序的一些GC Root(比如運(yùn)行中的線程棧里的方法棧幀中本地變量表、操作數(shù)表中的引用、靜態(tài)變量引用等)開(kāi)始通過(guò)引用進(jìn)行引用圖遍歷,如果在JVM遍歷的過(guò)程中mutator也在運(yùn)行,則mutator則可能會(huì)修改這個(gè)對(duì)象圖的引用關(guān)系,如果JVM不對(duì)這種并發(fā)修改進(jìn)行特殊處理,可能導(dǎo)致一些非可回收對(duì)象沒(méi)有被遍歷到,從而被標(biāo)記成垃圾對(duì)象而被錯(cuò)誤的回收。(切記標(biāo)記的都是存活的對(duì)象,而不是要被清除的,此外不會(huì)之遍歷不到就會(huì)被立刻回收,還需要考慮finalize方法進(jìn)行再一次判斷)。
如果要完全并發(fā)GC,JVM的實(shí)現(xiàn)成本會(huì)比較大,并且很多情況下整體的吞吐量是會(huì)降低的。(聯(lián)想下并發(fā)編程中cas原子操作和加鎖的使用,如果競(jìng)爭(zhēng)比較激烈使用加鎖效率更高,因?yàn)槟軌驕p少cas循環(huán)的cpu消耗)
因此在很多GC收集器中都會(huì)有一些StopTheWorld階段,這個(gè)StopTheWorld就是safepoint。在safepoint中不會(huì)有mutator操作對(duì)象,并且線程棧和heap中每個(gè)位置的數(shù)據(jù)類型也是確定的(比如一個(gè)8bit的數(shù)據(jù)是long還是對(duì)象引用)。
一個(gè)線程要么在safepoint中,要么不在safepoint中。上面提到的StopTheWorld指的是全局safepoint(針對(duì)hotspot),也就是要求所有線程都處于safepoint狀態(tài)。后面如果沒(méi)有特別說(shuō)明safepoint也指的是全局safepoint。
在hotspot實(shí)現(xiàn)中safepoint是協(xié)作式的,當(dāng)JVM需要mutator進(jìn)入safepoint時(shí),會(huì)設(shè)置一個(gè)狀態(tài)標(biāo)記表示要進(jìn)入safepoint了,每個(gè)mutator線程都會(huì)在合適的時(shí)機(jī)檢查這個(gè)狀態(tài)標(biāo)記,如果發(fā)現(xiàn)需要進(jìn)入safepoint則會(huì)暫停自己。
這里的合適的時(shí)機(jī)的選取,既要不那么頻繁,避免增大運(yùn)行時(shí)開(kāi)銷(不能每走一步看一次),也不能太久不檢查,避免進(jìn)入safepoint進(jìn)入太慢(需要線程們都進(jìn)入safepoint狀態(tài)才行,如果有一個(gè)線程一直干活不檢查safepoint會(huì)影響其他線程,畢竟其他線程都在等著)。
如果是compiled code(JIT編譯后的代碼),JIT會(huì)在某些地方插入檢查代碼,比如方法調(diào)用返回和循環(huán)跳回的地方。
如果是interpreted code(解釋執(zhí)行),JVM有兩個(gè)字節(jié)碼分發(fā)表,如果需要進(jìn)入safepoint,則JVM會(huì)切換到有safepoint狀態(tài)檢查的那個(gè)分發(fā)表上。
為了盡量減少開(kāi)銷,hotspot中safepoint的狀態(tài)檢查的實(shí)現(xiàn)方式是讀取一個(gè)內(nèi)存值,如果需要進(jìn)入safepoint,則將這個(gè)內(nèi)存頁(yè)設(shè)置成被保護(hù)的,這樣就會(huì)觸發(fā)一個(gè)page fault,然后就可以通過(guò)異常處理進(jìn)入safepoint了。這種方式比準(zhǔn)確讀取一個(gè)內(nèi)存值(比如一個(gè)boolean數(shù)據(jù))要輕量(因?yàn)樾枰獌?nèi)存同步)
大家可能會(huì)想到如果一個(gè)線程處于sleep,線程在執(zhí)行JNI代碼時(shí)也處于safepoint中,并且其他的”阻塞”狀態(tài)也是在safepoint中,比如Thread.sleep,如果要退出線程要退出safepoint需要JVM允許,這樣就不會(huì)出現(xiàn)sleep狀態(tài)的線程在其他線程進(jìn)入safepoint后突然運(yùn)行這種情況了。
除了一些GC階段需要safepoint內(nèi)執(zhí)行,其他的比較常見(jiàn)的操作有。
(偏向鎖撤銷,頻繁看到偏向鎖撤銷可以考慮關(guān)閉偏向鎖-XX:-UseBiasedLocking)
無(wú)論是通過(guò)jstack還是通過(guò)jmx的,ThreadMXBean.getThreadInfo(maxDepth>0的情況)還是Thread.getAllStackTraces等方法,都會(huì)觸發(fā)safepoint,如果線程非常多則可能導(dǎo)致比較長(zhǎng)時(shí)間的暫停。
(通過(guò)Instrument對(duì)象對(duì)類進(jìn)行retransform或redefine)
在JVM啟動(dòng)參數(shù)上增加一些參數(shù)可以打印出應(yīng)用暫停和safepoint相關(guān)信息。
如果版本<=jdk8
-XX:+PrintGCApplicationStoppedTime -XX:+PrintGCApplicationConcurrentTime -XX:+PrintSafepointStatistics -XX:PrintSafepointStatisticsCount=1
如果版本>jdk8
-Xlog:gc*=info::time,tags,tid -Xlog:safepoint=info::time,tags,tid
[2020-05-18T09:18:55.978-0800][19459][safepoint ] Application time: 1.0038747 seconds [2020-05-18T09:18:55.978-0800][19459][safepoint ] Entering safepoint region: ThreadDump [2020-05-18T09:18:55.980-0800][19459][safepoint ] Leaving safepoint region [2020-05-18T09:18:55.980-0800][19459][safepoint ] Total time for which application threads were stopped: 0.0017502 seconds, Stopping threads took: 0.0000312 seconds
這個(gè)表示應(yīng)用線程運(yùn)行了1.0038747秒后,因?yàn)門(mén)hreadDump開(kāi)始進(jìn)入safepoint,應(yīng)用線程被暫停了0.0017502秒,暫停這些線程花了0.0000312秒
到此,關(guān)于“SafePoint安全點(diǎn)是什么”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請(qǐng)繼續(xù)關(guān)注億速云網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)?lái)更多實(shí)用的文章!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。