jvm區域整體分兩類,heap區和非heap區。heap區又分:Eden Space(伊甸園)、Survivor Space(倖存者區)、Tenured Gen(老年代-養老區)。 非heap區又分:Code Cache(代碼緩存區)、Perm Gen(永久代)、Jvm Stack(java虛擬機棧)、Local Method Statck(本地方法棧)。 php
HotSpot虛擬機GC算法採用分代收集算法: html
1、一我的(對象)出來(new 出來)後會在Eden Space(伊甸園)無憂無慮的生活,直到GC到來打破了他們平靜的生活。GC會逐一問清楚每一個對象的狀況,有沒有錢(此對象的引用)啊,由於GC想賺錢呀,有錢的才能夠敲詐嘛。而後富人就會進入Survivor Space(倖存者區),窮人的就直接kill掉。 java
2、並非進入Survivor Space(倖存者區)後就保證人身是安全的,但至少能夠活段時間。GC會按期(能夠自定義)會對這些人進行敲詐,億萬富翁每次都給錢,GC很滿意,就讓其進入了Genured Gen(養老區)。萬元戶經不住幾回敲詐就沒錢了,GC看沒有啥價值啦,就直接kill掉了。 算法
3、進入到養老區的人基本就能夠保證人身安全啦,可是億萬富豪有的也會揮霍成窮光蛋,只要錢沒了,GC仍是kill掉。 數組
分區的目的:新生區因爲對象產生的比較多而且大都是朝生夕滅的,因此直接採用標記-清理算法。而養老區生命力很強,則採用複製算法,針對不一樣狀況使用不一樣算法。 緩存
非heap區域中Perm Gen中放着類、方法的定義,jvm Stack區域放着方法參數、局域變量等的引用,方法執行順序按照棧的先入後出方式。 安全
以上各類GC機制是須要組合使用的,指定方式由下表所示: jvm
源文檔 <http://blog.163.com/guixl_001/blog/static/4176410420108296361891/> 學習
源文檔 <http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=29632145&id=4616836> ui
回到問題「爲什麼會內存溢出?」。
要回答這個問題又要引出另一個話題,既什麼樣的對象GC纔會回收?固然是GC發現經過任何reference chain(引用鏈)沒法訪問某個對象的時候,該對象即被回收。名詞GC Roots正是分析這一過程的起點,例如JVM本身確保了對象的可到達性(那麼JVM就是GC Roots),因此GC Roots就是這樣在內存中保持對象可到達性的,一旦不可到達,即被回收。一般GC Roots是一個在current thread(當前線程)的call stack(調用棧)上的對象(例如方法參數和局部變量),或者是線程自身或者是system class loader(系統類加載器)加載的類以及native code(本地代碼)保留的活動對象。因此GC Roots是分析對象爲什麼還存活於內存中的利器。知道了什麼樣的對象GC纔會回收後,再來學習下對象引用都包含哪些吧。
源文檔 <http://www.blogjava.net/rosen/archive/2010/05/21/321575.html>
從最強到最弱,不一樣的引用(可到達性)級別反映了對象的生命週期。
l Strong Ref(強引用):一般咱們編寫的代碼都是Strong Ref,於此對應的是強可達性,只有去掉強可達,對象才被回收。
l Soft Ref(軟引用):對應軟可達性,只要有足夠的內存,就一直保持對象,直到發現內存吃緊且沒有Strong Ref時纔回收對象。通常可用來實現緩存,經過java.lang.ref.SoftReference類實現。
l Weak Ref(弱引用):比Soft Ref更弱,當發現不存在Strong Ref時,馬上回收對象而沒必要等到內存吃緊的時候。經過java.lang.ref.WeakReference和java.util.WeakHashMap類實現。
l Phantom Ref(虛引用):根本不會在內存中保持任何對象,你只能使用Phantom Ref自己。通常用於在進入finalize()方法後進行特殊的清理過程,經過 java.lang.ref.PhantomReference實現。
有了上面的種種我相信很容易就能把heap和perm gen撐破了吧,是的利用Strong Ref,存儲大量數據,直到heap撐破;利用interned strings(或者class loader加載大量的類)把perm gen撐破。
源文檔 <http://www.blogjava.net/rosen/archive/2010/05/21/321575.html>
Shallow size就是對象自己佔用內存的大小,不包含對其餘對象的引用,也就是對象頭加成員變量(不是成員變量的值)的總和。在32位系統上,對象頭佔用8字節,int佔用4字節,無論成員變量(對象或數組)是否引用了其餘對象(實例)或者賦值爲null它始終佔用4字節。故此,對於String對象實例來講,它有三個int成員(3*4=12字節)、一個char[]成員(1*4=4字節)以及一個對象頭(8字節),總共3*4 +1*4+8=24字節。根據這一原則,對String a=」rosen jiang」來講,實例a的shallow size也是24字節
源文檔 <http://www.blogjava.net/rosen/archive/2010/05/21/321575.html>