1. 程式人生 > >二: Jvm內存模型

二: Jvm內存模型

array sdn png 指針 方法 cas 多個 直接 釋放

為每個對象生命周期不一樣,jvm在做內存管理的時候,就幫我們分成了三個區域:

  1. 新生代(回收頻率高) 新生和老年默認大小比例為1:2

  2. 老年代(回收頻率低) 最好所有的對象都不要進入老年代,最好新生代能及時回收空對象釋放空間供下次使用。

  3. 永久代(一般放類的加載信息,常量,靜態變量)。

GC回收算法:

  GC回收是采用的復制回收算法,默認將新生代內存分為8:1:1,達到90%的利用率。

    創建的對象默認放在eden區中,eden區內存快滿的時候,就會觸發minor gc來回收空對象,將不能回收的對象放到s0區裏面;

    當再次創建多個對象後 eden區又快滿了,這時又觸發minor gc回收eden和s0裏面的空對象,若esdn區和s0區內存不足,將剩余的放到s1區中;

    如此反復新生代沒有空間時,對象就會放到老年代中。

技術分享圖片

  從上圖可以看出jdk1.8之前:新生代,老年代放在heap中, 永久代放在方法區中;

  在jdk1.8的時候,就將永久代放到了一塊叫Meta Space(元空間)的本地內存中。

  官方之所以這麽設計,是為了解決永久代會溢出的問題,meta space有點像ArrayList,擁有自動擴容的特性,從而防止溢出。當然它也不是越大越好,太大了會因為內存占用過多,從而使得堆外內存空間狹小而容易出現內存溢出的情況。這些都是可配置的。

  

指針碰撞:

  如下圖,第一次創建對象的時候線程開辟了一個空間,第二次創建對象線程所有開了了一個空間,如果多個線程同時創建就會出現“搶占”空間的情況出現指針碰撞,jvm就通過CAS來控制先來

後到的順利,理解成線程鎖一樣。但是這樣創建對象還是CAS還是會出現競爭激烈的情況從而消耗CPU影響性能。為了解決這個問題,jvm又提供了棧上分配。內存規整(即內存連續有規律)

  技術分享圖片

棧上分配:

  棧上分配的本質還是在堆中分配內存。

  如下圖:在堆裏面,每個線程都有自己的Thread local Alltion Buffer,他們都是在自己的空間裏面創建對象,這樣就不會出現搶占的情況了,從而提高了性能。技術分享圖片

對象分配規則:

  (1)對象優先分配在Eden區,如果Eden內存不夠,虛擬機就執行一次Minor GC

  (2)大對象(大對象指需要大量連續內存空間的對象)直接進入老年代.這樣做的目的是避免在Eden區和兩個Survivor區之間發生大量的內存拷貝(新生代采用復制算法收集內存)。

  (3)長期存活的對象進入老年代.虛擬機為每個對象都定義一個年齡計數器,如果對象經過一次Minor GC就去Survivor區,之後每經過一次Minor GC,年齡就會加一,直到15之後就去老年代.

  (4)動態判斷對象的年齡.如果Survivor區相同年齡的對象的總和大於Survivor的一半,那麽大於或者等於這個年齡的對象直接去老年代

二: Jvm內存模型