jvm堆內存分布及gc發生的條件


  jvm虛擬機對內存管理主要體現在堆內存的管理上,我們可以在啟動jvm的時候設置jvm對內存大小及調整策略。

  1.jvm啟動參數:

    -Xms:jvm啟動時初始堆大小。

    -Xmx:jvm堆的最大值。

    -Xss:線程棧大小。

    -Dname=value:jvm全局屬性設置。

  jvm啟動參數設置有很多,以上只是列舉本人接觸過的幾個參數。

  1)首先,-Xms是jvm啟動時堆內存的初始大小,當堆內存不夠用時,jvm調整堆大小到-Xmx設置的大小。一般resin這些服務器會把-Xms和-Xmx大小設置一樣以避免不必要的內存調整。第一次對這個參數有印象是在剛到公司實習的第二天,公司使用的項目是用maven編譯的,在maven配置文件settings.xml中有maven的資源庫位置以及編譯的各項配置。看完各種新手入門教程之后開始下載部門主工程代碼,用maven編譯一直通過不了,原因就在於jvm內存不夠,當時maven中設置-Xms:256m,-Xmx:256m,顯然256m是不夠的,-Xmx設置為512m之后就可以編譯過了。還有一個問題就是,這里把-Xms和-Xmx設置一樣大是不合理的,雖然兩個大小設置一樣會避免編譯主工程的時候jvm調整堆內存大小,但是maven編譯其他比較小的項目的時候也要分配512m有些過於浪費,jvm占用過多的內存會讓機器很卡的。

  2)-Dname=value這個參數使用的更頻繁,在resin的httpd.sh文件中配置這個參數可以在項目啟動的時候將指定的域名映射到想要的ip上去,使得調試更為方便。其他作用的設置暫時還不了解。

  

  2.jvm堆內存分布

  剛剛畢業的時候,面試官問jvm內存知道么,我會脫口而出jvm內存分為堆和棧。直到第一次代碼不小心造成了內存泄露,當時tail了一下resin的jvm.log發現gc和full gc的頻率很高,正常情況下tail這個日志很少會有gc或者full gc。看着一條一條jvm日志,完全像是在看另外一個世界的東西,這時我才意識到jvm管理的內存只知道這些是不夠的。

    

  事實上jvm虛擬機管理的內存主要有:程序計數器,堆,方法區(永久代),虛擬機棧,本地方法棧。堆是jvm管理的最大的一塊內存,主要的作用:存放幾乎所有的類的實例對象。

  首先,jvm對內存分為新生代(Young)和老年代(Old).新生代又可以划分為三塊,這樣jvm中就有新生代,老年大,永久代幾片內存,這樣分區的目的就是垃圾回收時使用分代算法。

   新生代被划分為三個區域:

      Eden:幾乎所有新誕生的java對象存在這個區域。

      From Survivor/To Survivor:經歷過gc之后仍然存活且未進入到老年代區域的對象。

  Young和Old大小比例是1:2,Young中Eden:From:To是8:1:1。這個比例由參數 -XX:SurvivorRatio=8 來決定的。

3.gc發生條件

  首先,一般的對象產生都會在Eden中,較大的對象會直接進入老年代這個由參數 -XX:PretenureSizeThreshold 設置。在新生代中三個區域eden,from,to,一個時刻只會有兩片內存被使用,首先eden肯定會被使用,from和to只有一片會被使用,主要是由於虛擬機采用的復制算法。

  minor gc:為了避免在gc的時候產生內存碎片,jvm以犧牲空間的方式來做的,首先eden空間不足時會產生一次minor gc,垃圾回收器會在eden和一片使用的Survivor(假設是from)中進行清理,存活下來的對象會被復制到to中(假設to的大小足夠裝滿),然后清空eden和from,保留下來的對象年齡加一。當年齡到達某一個設定值時會進入老年代,默認是15歲,由參數 -XX:MaxTenuringThreshold設置。還有一種情況是在Survivor區域相同年齡多有對象大於Survivor區域一半是所有該年齡及以上的都會被移動到老年代。

  full gc:minor gc時Survivor區域不足以容納年輕代中存活下來的對象時,且老年代中剩余空間容納不了新生代中存活下來的對象時會進行full gc。老年代中因為沒有進行分區,所以回收算法使用的是標記-清理算法或者標記整理算法。

4.gc日志解讀

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM