Java記憶體模型以及gc演算法
阿新 • • 發佈:2019-02-18
1.java記憶體模型
- JVM堆記憶體分為2塊:Permanent Space 和 Heap Space。
- Permanent 即 持久代(Permanent Generation),主要存放的是Java類定義資訊,與垃圾收集器要收集的Java物件關係不大。持久代 用於存放類資訊,靜態型別資料,final修飾的變數,常量,方法,如 Java Class, Method 等。持久代對垃圾回收沒有顯著影響。但是有些應用可能動態生成或呼叫一些Class。方法區都儲存在持久代。
- Heap = { Old + NEW = {Eden, from, to} },Old 即 年老代(Old Generation),New 即 年輕代(Young Generation)。年老代和年輕代的劃分對垃圾收集影響比較大。
2)年老代: 在年輕代中經歷了N次(可配置)垃圾回收後仍然存活的物件,就會被複制到年老代中。
- 當一組物件生成時,記憶體申請過程如下:
2).當Eden區空間足夠時,記憶體申請結束。否則執行下一步。
3).JVM試圖釋放在Eden區中所有不活躍的物件(Young GC)。釋放後若Eden空間仍然不足以放入新物件,JVM則試圖將部分Eden區中活躍物件放入Survivor區。
4).Survivor區被用來作為Eden區及年老代的中間交換區域。當年老代空間足夠時,Survivor區中存活了一定次數的物件會被移到年老代。
5).當年老代空間不夠時,JVM會在年老代進行完全的垃圾回收(Full GC)。
6).Full GC後,若Survivor區及年老代仍然無法存放從Eden區複製過來的物件,則會導致JVM無法在Eden區為新生成的物件申請記憶體,即出現“Out of Memory”。
圖片來源:http://www.cnblogs.com/kabi/p/5171406.html
2.“Out of Memory”原因
OOM(“Out of Memory”)異常一般主要有如下2種原因:
- 年老代溢位,表現為:java.lang.OutOfMemoryError:Javaheapspace。這是最常見的情況,產生的原因可能是:
- 持久代溢位,表現為:java.lang.OutOfMemoryError:PermGenspace。
通常由於持久代設定過小,動態載入了大量Java類而導致溢位 ,解決辦法唯有將引數 -XX:MaxPermSize 調大(一般256m能滿足絕大多數應用程式需求)。將部分Java類放到容器共享區(例如Tomcat share lib)去載入的辦法也是一個思路,但前提是容器裡部署了多個應用,且這些應用有大量的共享類庫。
3.gc型別
- Minor gc:發生在Eden區空間不足時,會導致應用程式的執行緒短暫的暫停。在Eden這裡使用空閒指標來指著最後一個被分配的物件,每次要求分配空間時,先判斷空閒指標在Eden的位置,判斷是否有足夠記憶體來分配。若不夠,則進行Copying演算法,jvm將Eden的存活物件Copy到Survivor區,最後讓Eden清空。
- Major gc/Full gc:發生在Eden區或者Survivor的物件要求放入年老區,年老區空間不足。此時採用標記(Mark)演算法,將所有物件(所有區)掃描一次,標記存活的物件,然後回收未標記的物件。接著對剩下的空間要麼進行合併(compact),要麼標記出來便於下次分配。
4.gc中判斷物件是否存活的演算法
- 引用計數法:給物件增加一個引用計數器,有引用指向它時就加1,引用失效時就減1。當計數器為0時,表示該物件失效。(但可能會出現迴圈引用的問題,導致物件無法釋放)
- 根搜尋法:通過一系列“GCRoots”的物件為起點,從這些節點往下搜尋,經過的路徑成為引用鏈。當一個物件不在任何一條引用鏈上時,該物件失效。