Java 內存管理 堆和棧 GC 垃圾回收 Garbage Collection
來自: http://blog.csdn.net//never_cxb/article/details/48174961
Java GC 垃圾回收 Garbage Collection
參加這篇博客
java 運行時內存分配 堆和棧區別</blockquote>
程序計數器(Program counter Register)
這是線程私有的, 標記線程執行到哪兒了, 線程切換了也可以回到它本來運行中斷的地方
java 虛擬機的多線程是通過線程輪流切換并分配處理器執行時間的方式來實現的, 為了線程切換后能到恢復到正確的執行位置, 每個線程都要有個獨立的程序計數器
java 虛擬機棧
棧幀用來存放局部變量表 操作數棧 方法出口等
每一個方法從調用直至執行完成的過程, 就對應著一個棧幀在虛擬機棧中入棧和出棧的過程
局部變量表存放了編譯器已知的基本數據類型, 對象引用
操作數棧也是以字長為單位的數組, 它只能進行入棧出棧的基本操作. 在進行計算時, 操作數被彈出棧, 計算完畢后再入棧.
本地方法棧
這是Native method 本地方法執行需要的棧
java 堆
分為新生代和老年代, 新生代空間小, 老年代空間大, 這些可以通過參數設置, 也可以設置這幾個區域的垃圾回收策略
新生代朝生夕死, 適合用一個大區域, 2 個小區域來回收. 用”標記- 復制” 的方法回收, 減少碎片, 復制后留下來的區域整體情況, 可以得到一個連續的內存快
老年代是大對象存放的地方, 或者是新生代中熬了個幾次回收的對象, 具體多少次可以設置
老年代可能100%存活, “標記- 復制”方法不適用, 需要用”標記- 整理”方法, 這是對”標記- 清除”方法的改進, 清除會帶來碎片. 標記- 整理將存活的對象向一段移動, 然后清理掉邊界以外的內存
Java 內存區域補充
線程共享的區域有 Java 堆(java heap) 和 方法區域(method area)
回收內存也主要針對這兩個區域java 堆
所有的對象實例以及數組都在堆上分配, 堆可以處于物理上不連續的區域
方法區
Method Area 存儲已被虛擬機加載的類信息 常量 靜態變量 即時編譯器編譯后的代碼等數據
運行時常量池是方法區的一部分, 它存放編譯器生成的各種字面量和符號引用
HotSpot 用永久代(Permanent Generation)實現方法區, 但現在改用 Native Memory 實現方法區
運行時常量池
class 文件除了有類的版本 字段 方法 接口等描述信息外, 還有一項信息就是常量池
它保存了編譯器生成的各種字面量和符號引用
常見誤解說法
給對象添加一個引用計數器, 每當有一個地方引用它時, 計數器+1;
當引用失效時, 計數器-1;
任何時刻計數器為0的對象就是不可能被引用的可達性分析算法
通過 GC Roots 的對象作為起始點, 從這些節點開始往下搜索, 搜索走過的路徑稱為引用鏈(Reference Chain), 當一個對象到 GC Roots 沒有任何引用鏈相連時(即 GC Roots 到這個對象不可達), 此時這個對象就是不可用的
可作為 GC Roots的對象
- 虛擬機棧(棧幀中的本地變量表)中引用的對象
- 方法區中類靜態屬性引用的對象
- 方法區中常量引用的對象
- 本地方法棧中 JNI (即一般說的 Native 方法) 引用的對象
## 新生代(Young Generation) 老年代(Old Generation)##
新生代中, 每次垃圾回收都有大批對象死去, 可以使用復制算法, 只需要少量存活對象的復制成本就可以完成回收
老年代中, 對象存活率較高, 沒有額外的空間對它進行分配擔保, 必須使用”標記–整理”算法進行回收
</div>