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