1. 程式人生 > >JDK8 JVM效能優化-1

JDK8 JVM效能優化-1

原文地址:https://blog.csdn.net/xingkongtianma01/article/details/80689928

 

大 多數情況下,我們並不需要關心JVM的底層,但是如果瞭解它的話,對於我們系統調優是非常有用的,在這裡面瞭解JVM的GC原理,是非常重要的一塊知識。 我們都知道對於一個大型網站,如果JVM頻繁發生FULL GC,那麼將會是致命的危險,不僅僅會造成網站響應遲鈍,更嚴重的時候會導致系統崩潰,這對使用者體驗來講,都是我們不願意看到的。 

在JVM裡的記憶體空間,從大的層面劃分,主要有新生代空間(Young)和老年代空間(Old),其中Young空間,又被分為2個部分和3個板塊,分別是1個Egen區,和2個Survivor區,看下圖: 

OK,下面來具體看下,每部分都是幹啥的 
(1)Eden區域是用來存放使用new或者newInstance等方式建立的物件,預設都是存放在Eden區,除非這個物件太大,或者超過了設定的閾值-XX:PretenureSizeThresold,這樣的物件會被直接分配到Old區域。 

(2)2個Survivor(倖存)區,一般稱S0,S1,理論上他們是一樣大的,解釋一下,他們是如何工作的: 
在不斷建立物件的過程中,Eden區會滿,這時候會開始做Young G也叫Minor GC,而Young空間的第一次GC就是找出Eden區中,倖存活著的物件,然後將這些物件,放到S0,或S1區中的其中一個, 假設第一次選擇了S0,它會逐步將活著的物件拷貝到S0區域,但是如果S0區域滿了,剩下活著的物件只能放old區域了,接下來要做的是,將Eden區域 清空,此時時候S1區域也是空的。 

當第二次Eden區域滿的時候,就將Eden區域中活著的物件+S0區域中活著的物件,遷移到S1中,如果S1放不下,就會將剩下的部門,放到Old區域中,只是這次物件來源區域增加了S0,最後會將Eden區+S0區域,清空 

第三次和第四次依次類推,始終保證S0和S1有一個是空的,用來儲存臨時物件,用於交換空間的目的,反反覆覆多次沒有被淘汰的物件,將會放入old區域中,預設是15次。具體的交換過程就和上圖中的資訊相似。 




問題一:怎麼定義活著的物件? 
從根引用開始,物件的內部屬性可能也是引用,只要能級聯到的都被認為是活著的物件 

問題二:什麼是根? 
本地變數引用,運算元棧引用,PC暫存器,本地方法棧引用等這些都是根。 

問題三:物件進入Old區域有什麼壞處? 
old區域一般稱為老年代,老年代與新生代不一樣,年輕代,我們可以認為存活下來的物件很少,而老年代則相反,存活下來的物件很多,所以JVM的 堆記憶體,才是我們通常關注的主戰場,因為這裡面活著的物件非常多,所以發生一次FULL GC,來找出來所有存活的物件是非常耗時的,因此,我們應該儘量避免FULL GC的發生。 

問題四:S0和S1一般多大,靠什麼引數來控制,有什麼變化? 

一般來說很小,我們大概知道它與Young差不多相差一倍的比例,設定的的引數主要有兩個: 
-XX:SurvivorRatio=8 
-XX:InitialSurvivorRatio=8 

第一個引數是Eden和Survivor區域比重,注意是一個Survivor的的大小,如果將其設定為8,則說明Eden區是一個Survivor區的8倍,換句話說S0或S1空間是整個Young空間的1/10,剩餘的80%由Eden區域來使用。 

第二個引數是Young/S0的比值,當其設定為8時,表示s0或s1佔整個Young空間的12.5%。 


問題五;一個物件每次Minor Gc時,活著的物件都會在s0和s1區域轉移,經過經過Minor GC多少次後,會進入Old區域呢? 

預設是15次,引數設定-XX:MaxTenuringThreshold=15,計數器會在物件的頭部記錄它交換的次數 


問題六:為什麼發生FULL GC會帶來很大的危害? 

在發生FULL GC的時候,意味著JVM會安全的暫停所有正在執行的執行緒(Stop The World),來回收記憶體空間,在這個時間段內,所有除了回收垃圾的執行緒外,其他有關JAVA的程式,程式碼都會靜止,反映到系統上,就會出現系統響應大幅度變慢,卡機等狀態。 

舉個通俗易懂點的例子,就是在一個房間裡,如果有一個人,不停的扔垃圾,然後有一個清潔工不停掃垃圾,這時候,我們的系統是OK的,因為基本不會 出現垃圾堆滿房間的情景,而且因為清潔工可以對付過來,假設現在有10個人不停扔垃圾,那麼就房間就會很快被堆滿,這時候清潔工,由於工作不過來了,大聲 吼一聲,你們都暫停3分鐘,別再扔了,我先把這個房間打掃完,你們才可以扔。 
在這個場景中,一個人扔,一個人掃,就類似於Minor GC,這時候,並不會影響扔垃圾的人,然後一旦10個人同時仍,而且很快就沒地方仍了,這時候,就會觸發Full GC,然後JVM下令,你們暫時都別仍了,等我什麼時候回收完垃圾了,你們在仍,現在大家清楚了吧,所謂的10個人,就是類似我們成千上百的java類, 在不停的執行任務,所謂的清潔工,就是我們的GC機制,所以,大家在平時編碼的時候,一定注意儘量少造點垃圾物件,這樣觸發FULL GC的機率,才會變小。