Java GC簡單理解

情景

做Android開發OutOfMemory很常見,內存泄漏的問題也經常遇到,但不知道具體發生了什麼,所以簡單瞭解一下Java的garbage collection。

Java運行時內存劃分

程序計數器 Program Counter

一塊很小的空間,指示當前線程的執行的字節碼執行到了第幾行。
線程私有,每個線程單獨劃分。
執行java方法:記錄虛擬機字節碼指令地址
執行native方法:值爲undefined

虛擬機棧 Java Stack

執行java方法
一個線程的每個方法都創建一個幀棧(Stack Frame),幀棧存儲局部變量表、操作站、動態鏈接、方法出口等。
方法調用是幀棧壓棧到虛擬機棧,方法執行完成幀棧出棧。
線程私有

本地方法棧 Native Method Stack

等同與虛擬機棧,用來執行native方法。

堆區 Heap

存儲對象實例。
創建的對象實例全部放在堆區。
GC的主要理解區域

方法區

在GC中也稱爲永久代。
用於存儲已經被虛擬機加載的類信息、final常量、靜態變量、編譯器即時編譯的代碼等。
運行時常量池也包含在方法區,String常量池等。

Java內存分配機制

分代分配、分代回收。
在堆區中,分爲年輕代以及年老代,分別按照不同的算法進行垃圾收集。
由於絕大部分的對象都活不了多久,通過分代的方式提升GC性能。

年輕代 Young Generation

除超出年輕代空間的大對象,對象的創建首先分配到年輕代。
年輕代也分爲三個區域:Eden、Survivor0、Survivor1,按照8:1:1的大小進行劃分。

Eden

伊甸園區,對象創建的第一站。
Eden裝滿之後,針對整個年輕代進行Minor GC,這裏使用停止複製算法,仍然存活的對象放到空白的Survivor中,同時清空Eden和另一Survivor的所有空間。

Survivor

倖存者區,兩個對等的內存空間,必須保證一個空間爲空的狀態,存在一個空間內存的浪費,但是相較頻繁的Minor GC性能提升更大。
每次Minor GC將整個年輕代的存活對象放到空白的Sruvivor區,同時清空剩餘空間。
單次Minor GC超過Survivor空間,將部分對象存儲到年老代。
多次Minor GC任然存活的對象存儲到年老代。

年老代 Old Generation

存儲多次Minor GC任然存活的頑強對象和大對象,到了年老代的對象脫離了短命鬼區,只有當年老代慢了之後,觸發Full GC/Major GC,但是相較與Minor GC頻率低很多。這裏使用標記整理算法

永久代/方法區

永久代的GC不是必須的。

回收廢棄常量以及無用的類。
常量的回收很簡單,沒有引用了就可以被回收。
無用的類進行回收,必須保證3點:

  • 類的所有實例都已經被回收
  • 加載類的ClassLoader已經被回收
  • 類對象的Class對象沒有被引用(即沒有通過反射引用該類的地方)

算法具體分析

參考路徑:jvm:停止複製、標記清除、標記整理算法(垃圾回收)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章