天天看點

JVM中的Safepoints

簡介

java程式員都聽說過GC,大家也都知道GC的目的是掃描堆空間,然後将那些标記為删除的對象從堆空間釋放,以提升可用的堆空間。

今天我們會來探讨一下隐藏在GC背後的一個小秘密Safepoints。

GC的垃圾回收器

小師妹:F師兄,GC的垃圾回收器的種類為什麼會有這麼多呀?使用起來不是很麻煩。并且我聽說CMS在JDK9zhong已經被廢棄了。

小師妹,這麼多垃圾回收器實際是在JVM的發展過程中建立起來的,在之前的文章中,我們講到了目前的GC回收器有這樣幾種。

01

基于分代技術的回收器

Concurrent mark sweep (CMS) ,CMS是mark and swap的更新版本,它使用多個線程來對heap區域進行掃描,進而提升效率。

由于CMS的參數複雜性和性能問題,CMS已經在JDK9中被廢棄了。

Serial garbage collection,使用單一的線程來進行垃圾回收操作,其好處就是不需要和其他的線程進行互動。如果你是單核的CPU,那麼最好就是選擇Serial garbage collection,因為你不能充分利用多核的好處。同樣的它也常常用在比較小型的項目中。

Parallel garbage collection,如果你是多核處理器,那麼Parallel GC可能是你的選擇。

Parallel GC是JDK8中的預設GC。而在JDK9之後, G1是預設的GC。

G1 garbage collection,G1=Garbage First,它是為替換CMS而生的,最早出現在java7中。

G1将heap區域劃分成為多個更小的區域,每個小區域都被标記成為young generation 或者old generation。進而運作GC在更小的範圍裡運作,而不是影響整個heap區域。

02

非基于分代技術的回收器

Z Garbage Collection,ZGC是一個可擴充的,低延遲的GC。ZGC是并發的,而且不需要停止正在運作的線程。

ZGC是在JDK11中引入的。

當然還有正在研發中的其他GC。

分代回收器中的問題

小師妹:F師兄,分代回收器不好嗎?為什麼還有新的ZGC等基于非分代技術的回收器?

分代垃圾回收器中有一個非常常見的現象就是”Stop The World”。什麼是Stop the world呢?

就是說在GC的時候,為了進行垃圾回收,需要所有的線程都要暫停執行。所有的線程都暫停執行。

當然G1雖然是基于分代技術,但是G1實際上是不會”Stop The World”的。

JVM定義了一些Root對象,從這些對象開始,找出他們引用的對象,組成一個對象圖。所有在這個圖裡面的對象都是有效的對象,反之不在對象圖中的對象就應該被回收。有效的對象将會被Mark為alive。

這些Root對象包括:正在執行的方法中的本地對象和輸入參數。活動的線程,加載類中的static字段和JNI引用。

safepoints

為了實作STW的功能,JVM需要提供一個機制,讓所有的線程可以在某一個時刻同時停下來。這個停下來的時刻就叫做safepoints。

注意,這些停下來的線程不包括運作native code的線程。因為這些線程是不屬于JVM管理的。

JVM中的代碼執行其實有兩種方式,一種是JIT編譯成為機器碼,一種是解釋執行。

在JIT中,直接将檢查代碼編譯進入了機器碼中。通過設定相應的标記位,進而線上程運作的過程中執行暫停的指令。

還是舉一個上篇文章中我們提到的JMH的例子:

@Benchmark
    public void test1() {
        int length = array.length;
        for (int i = 0; i < length; i=i+1)
            array[i] ++;
    }           

複制

我們看一下它的assembly code:

JVM中的Safepoints

可以看到其中有個test的指令,這個test指令就是生成的safe points。

通過設定标志位,就可以線上程運作時執行暫停操作。

如果是解釋執行的話,JVM儲存了兩個位元組碼的排程table,當需要safepoint的時候,JVM就進行table的切換,進而開啟safepoint。

safepoint一般用在什麼地方

一般情況下,GC,JIT的反代碼優化,重新整理code cache,類重定義 ,偏向鎖撤銷和其他的一些debug操作。

我們可以通過使用

-XX:+PrintGCApplicationStoppedTime           

複制

來print safepints的暫停時間。

-XX:+PrintSafepointStatistics –XX:PrintSafepointStatisticsCount=1           

複制

這兩個參數可以強制JVM列印safepoint的一些統計資訊。

總結

Safepoint是垃圾回收中一個非常重要的概念,希望大家能夠有所了解。