java8 虛擬機(運行時數據區域,垃圾回收)

參考以下文章
Java 虛擬機
Java 虛擬機是什麼
深入理解java虛擬機
JVM內存模型總結
Java內存區域(運行時數據區域)和內存模型(JMM)

1 虛擬機是一個普通進程。
2 類加載器加載class文件。
3 執行引擎用來執行class文件中的字節碼指令
4 虛擬機在執行過程中,要分配內存創建對象。當這些對象過時無用了,必須要自動清理這些無用的對象。垃圾收集器負責清理對象回收內存的任務由。。

一.Java運行時數據區域

在這裏插入圖片描述
下圖是 JDK8 之後的 JVM 內存佈局。
在這裏插入圖片描述
在這裏插入圖片描述

1.程序計數器(PC Register)

是最小的一塊內存區域,它的作用是當前線程所執行的字節碼的行號指示器,在虛擬機的模型裏,字節碼解釋器工作時就是通過改變這個計數器的值來選取下一條需要執行的字節碼指令,分支、循環、異常處理、線程恢復等基礎功能都需要依賴計數器完成。

2.虛擬機棧(JVM Stack)

在這裏插入圖片描述
描述的是java方法執行的內存模型:每個方法被執行的時候都會創建一個"棧幀",用於存儲局部變量表(包括參數)、操作棧、方法出口等信息。**每個方法被調用到執行完的過程,就對應着一個棧幀在虛擬機棧中從入棧到出棧的過程。**聲明週期與線程相同,是線程私有的。
棧幀由三部分組成:
(1)局部變量區:被組織爲以一個字長爲單位、從0開始計數的數組。放編譯期可知的各種基本數據類型,引用類型,局部變量表的大小在編譯期便已經可以確定,在運行時期不會發生改變。
(2)操作數棧:一個以字長爲單位的數組。而是通過入棧和出棧來訪問的,可以看作爲臨時數據的存儲區域。
(3)幀數據區:支持常量池解析的數據、正常方法返回以及異常派發機制。

3.本地方法棧(Native Stack)

在這裏插入圖片描述

本地方法棧爲虛擬機執行native方法服務

4.堆(Heap)

在這裏插入圖片描述
該內存區域存放了對象實例及數組(但不是所有的對象實例都在堆中)
是垃圾收集的主要區域(“GC 堆”)。
現代的垃圾收集器基本都是採用分代收集算法,其主要的思想是針對不同類型的對象採取不同的垃圾回收算法。可以將堆分成兩塊:
新生代(Young Generation)
老年代(Old Generation)
可以通過 -Xms 和 -Xmx 這兩個虛擬機參數來指定一個程序的堆內存大小,第一個參數設置初始值,第二個參數設置最大值。

java -Xms1M -Xmx2M HackTheJava

5.方法區(Method Area)

用於存放已被加載的類信息、常量、靜態變量、即時編譯器編譯後的代碼等數據。
從 JDK 1.8 開始,移除永久代,並把方法區移至元空間,它位於本地內存中,而不是虛擬機內存中。元空間存儲類的元信息,靜態變量和常量池等放入堆中。

6.運行時常量池(Runtime Constant Pool )

運行時常量池是方法區的一部分。
Class 文件中的常量池(編譯器生成的字面量和符號引用)會在類加載後被放入這個區域。
除了在編譯期生成的常量,還允許動態生成,例如 String 類的 intern()。

7.直接內存(Direct Memory)

直接內存並不是虛擬機內存的一部分,也不是Java虛擬機規範中定義的內存區域。jdk1.4中新加入的NIO,引入了通道與緩衝區的IO方式,它可以調用Native方法直接分配堆外內存,這個堆外內存就是本機內存,不會影響到堆內存的大小.

二.垃圾回收

在這裏插入圖片描述

1. 引用計數算法

爲對象添加一個引用計數器,當對象增加一個引用時計數器加 1,引用失效時計數器減 1。引用計數爲 0 的對象可被回收。
在兩個對象出現循環引用的情況下,此時引用計數器永遠不爲 0,導致無法對它們進行回收。正是因爲循環引用的存在,因此 Java 虛擬機不使用引用計數算法。

public class Test {

    public Object instance = null;

    public static void main(String[] args) {
        Test a = new Test();
        Test b = new Test();
        a.instance = b;
        b.instance = a;
        a = null;
        b = null;
        doSomething();
    }
}

在上述代碼中,a 與 b 引用的對象實例互相持有了對象的引用,因此當我們把對 a 對象與 b 對象的引用去除之後,由於兩個對象還存在互相之間的引用,導致兩個 Test 對象無法被回收。

2. 可達性分析算法

以 GC Roots 爲起始點進行搜索,可達的對象都是存活的,不可達的對象可被回收。

Java 虛擬機使用該算法來判斷對象是否可被回收,GC Roots 一般包含以下內容:

(1)虛擬機棧中局部變量表中引用的對象
(2)本地方法棧中 JNI 中引用的對象
(3)方法區中類靜態屬性引用的對象
(4)方法區中的常量引用的對象

待補充……

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