溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

SafePoint安全點(diǎn)是什么

發(fā)布時(shí)間:2021-10-13 11:12:03 來(lái)源:億速云 閱讀:167 作者:iii 欄目:編程語(yǔ)言

這篇文章主要介紹“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ā)者有哪些需要注意的地方。

SafePoint安全點(diǎn)是什么

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。

safepoint是如何實(shí)現(xiàn)的

JVM如何通知線程進(jìn)入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ā)表上

各個(gè)線程如何檢查是否要進(jìn)入safepoint

為了盡量減少開(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)行這種情況了。

有哪些會(huì)引發(fā)safepoint的情況

除了一些GC階段需要safepoint內(nèi)執(zhí)行,其他的比較常見(jiàn)的操作有。

revoke bias

(偏向鎖撤銷,頻繁看到偏向鎖撤銷可以考慮關(guān)閉偏向鎖-XX:-UseBiasedLocking)

dump線程棧

無(wú)論是通過(guò)jstack還是通過(guò)jmx的,ThreadMXBean.getThreadInfo(maxDepth>0的情況)還是Thread.getAllStackTraces等方法,都會(huì)觸發(fā)safepoint,如果線程非常多則可能導(dǎo)致比較長(zhǎng)時(shí)間的暫停。

class redefinition

(通過(guò)Instrument對(duì)象對(duì)類進(jìn)行retransform或redefine)

code deoptimization

如何排查safepoint相關(guān)問(wèn)題

在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

一個(gè)示例

[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í)用的文章!

向AI問(wèn)一下細(xì)節(jié)

免責(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)容。

AI