【JVM 學習】ParNew 爲什麼要STW

 

  • Serial 和 ParNew 在進行垃圾回收時,爲什麼需要stop the world?不stop thw world 可以嗎?

在進行標記的時候,如果工作線程不停止的話,那麼肯定會有新對象生成。這些對象是沒有被標記的,裏面可能有存活的對象,也可能有已經沒有被引用的垃圾對象。那麼在標記完後,進行回收時。要如何回收?

因爲Serial 和 ParNew 是採用的複製算法。回收的時候,是需要把存活對象移到Survivor中的。而那些沒有被標記的,有存活的,也有垃圾對象。顯然不能全部移動到survivor 中的。

所以,在進行新生代回收的時候,是需要stop the world 的。

 

  • CMS 進行垃圾回收的時,爲什麼有些階段,工作線程可以不停止?

在CMS 回收器中,回收是分爲四個階段的。初始標記、併發標記、重新標記、併發清理。其中,併發標記和併發清理是可以不停止工作線程的。

這裏之可以不停止工作線程。也是和CMS 採用的回收算法有關的。

1、併發標記階段

這個是比較耗時的,工作線程可以不停止。那麼就有可能會有新對象進入老年代。這些新進入的對象。在重新標記階段。是會被標記的。所以,這個階段可以不停止工作線程。不過這個階段對系統負載也是很高的(回收線程和工作線程同時存在)。

2、併發清理階段

這個也是比較耗時的,工作線程也可以不停止。這裏也有可能有新對象進入老年代的。這時候這些都是沒有被標記的。其實,這裏沒有被標記的,就相當於不會被回收了。而CMS 採用的是標記-清理算法。這些沒有被回收的是不影響的,大不了下一次在進行回收。不像ParNew 採用的是複製算法。需要把存活的移動到survivor 中(ParNew 其實也可以把沒有標記的移動到survivor中,不過代價很大,因爲大概率survivor 放不下會導致進入老年代)。所以,併發清理階段,也是可以不停止工作線程的。

另外,在老年代回收時,有存活對象進入老年代的概率其實也是比較小的。大部分也會在新生代被回收掉。或者進入survivor區中。

 

這裏回收垃圾時,是否stop the world。其實跟採用的回收算法是相關的。

 

  • CMS 不停止工作線程,會有哪些問題?

如果不停止工作線程,那麼是有可能有存活對象進入老年代的。這時候就要有預留的空間給這些存活對象。所以,老年代回收時,不是等老年代滿了纔回收的。比如我們預留了10%空間,那麼老年代使用率達到90%的時候,就會進行垃圾回收(老年代垃圾回收的情況不止這種,比如還有老年代空間擔保機制,也可能會觸發垃圾回收的)。

另外,如果在垃圾回收的時候,有新存活對象進入老年代,並且總大小超過了10%時,這時候放不下了!要怎麼辦?這個時候,是會觸發 Concurrent Mode Failure 的。就是回收失敗。之後,就會退化爲 Serial old 垃圾回收器進行回收。會停止工作線程。重新標記,再回收。

 

所以,在CMS 中,爲了不停止工作線程。是有可能引入其他問題。比如上面 Concurrent Mode Failure。這時候效率就很低了。需要花費很長時間進行old gc。

對於發生了 Concurrent Mode Failure 的時候,就要進行分析。是程序業務邏輯的問題,還是預留的空間大小太小等等。

  •  

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章