Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> 細說JVM系列:JVM內存空間分區

細說JVM系列:JVM內存空間分區

編輯:關於Android編程

java虛擬機基本結構:

這裡寫圖片描述

JVM是一個內存中的虛擬機,那它的存儲就是內存了,我們寫的所有類、常量、變量、方法都在內存中,因此明白java虛擬機的內存分配非常重要,本部分主要講解java虛擬機內存分配。

本部分會從概念上介紹java虛擬機內存的各個區域,講解這些區域的作用、服務對象以及其中可能產生的問題。

引入:一個示例

下面通過一個簡單的示例,來展示java堆、方法區和java棧之間的關系。

public class SimpleHeap {
    private int id;

    public SimpleHeap(int id) {
        this.id = id;
    }

    public static void main(String[] args) {
        SimpleHeap s1 = new SimpleHeap(1);
        SimpleHeap s2 = new SimpleHeap(2);
        s1.show();
        s2.show();
    }

    public void show() {
        System.out.println("my id is" + id);
    }
}

\

一.程序計數器

1.定義

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

2.特點

線程私有。原因:由於java虛擬機的多線程是通過線程輪流切換並分配處理器執行時間的方式來實現的,在任何一個確定的時刻,一個處理器只會執行一條線程中的指令。因此,為了線程切換後能恢復到正確的執行位置,每條線程都需要有一個獨立的程序計數器,各條線程之間的計數器互不影響,獨立存儲,我們稱這類內存區域為“線程私有”的內存。 如果線程正在執行的是一個java方法,這個計數器記錄的是正在執行的虛擬機字節碼指令的地址;如果正在執行的是native方法,這個計數器值則為空。 此內存區域是唯一一個在java虛擬機規范中沒有規定任何outofmemoryerror的區域。

二.java虛擬機棧

1.定義

??虛擬機棧描述的是java方法執行的內存模型:每個方法在執行時都會創建一個棧幀用於存儲局部變量表、操作數棧、動態鏈接、方法出口燈信息。每個方法被調用直至執行完成的過程,就對應著一個棧幀在虛擬機棧中從入棧到出棧的過程。

??經常有人把java內存區域分為堆內存和棧內存,這種分法比較粗糙,java內存區域的劃分實際上遠比這復雜。這種劃分方式的流行只能說明大多數程序員最關注的,與對象內存分配關系最密切的內存區域是這兩塊。其中所指的棧就是這裡的棧,或者更具體說是虛擬機棧中的局部變量表部分。

??在java棧中保存的主要內容為棧幀。每一次函數調用,都會有一個對應的棧幀被壓入java棧,每一個函數調用結束,都會有一個棧幀被彈出java棧。如下圖所示,函數1對應棧幀1,函數2對應棧幀2,依次類推。函數1中調用函數2,函數2中調用函數3,函數3中調用函數4.當函數1被調用時,棧幀1入棧,當函數2被調用時,棧幀2入棧;當函數3被調用時,棧幀3入棧;當函數4被調用時,棧幀4入棧。當前正在執行的函數所對應的幀就是當前的幀(位於棧頂),它保存著當前函數的局部變量、中間結果等數據。

??當函數返回時,棧幀從java中被彈出。java方法有兩種返回函數的方式,一種是正常的函數返回,使用return指令,另外一種是拋出異常。不管使用哪種方式,都會導致棧幀被彈出。

\

備注:每次函數調用都會生成對應的棧幀,如果請求的棧深度大於最大的可用棧深度時,系統就會拋出stackoverflowerror棧溢出錯誤。

2.棧幀具體內容

在一個棧幀中,至少要包含局部變量表、操作數棧和幀數據區等幾個部分。

\

 

1)局部變量表

局部變量表存放了編譯器可知的各種基本數據類型(boolean,byte,char,short,int,float,long,double)、對象引用(reference類型,他不等同於對象本身,根據不同的虛擬機實現,它可能是一個指向對象起始地址的引用指針,也可能指向一個代表對象的句柄或者其他與此對象相關的位置)和return address類型(指向一條字節碼指令的地址)。

returnadress類型(A給命令於B,b反饋於A,這個時候A即為返回地址。)

局部變量表所需的內存空間在編譯期間完成分配,當進入一個方法時,這個方法需要在幀中分配多大的局部變量空間是完全確定的,在方法運行期間不會改變局部變量表的大小。

局部變量表用於保存函數的參數以及局部變量。局部變量表中的變量只在當前函數調用中有效,當函數調用結束後,隨著函數棧幀的銷毀,局部變量表也就隨之銷毀。

由於局部變量表在棧幀之中,因此,如果函數的參數和局部變量較多,會使得局部變量表膨脹,從而每一次函數調用都會占用更多的棧空間,最終導致函數的嵌套調用次數減少。

2)操作棧

操作數棧主要用於保存計算過程中的中間結果,同時作為計算過程中變量臨時的存儲空間。

操作數棧也是一個先進後出的數據結構,只支持入棧和出棧兩種操作。

把局部變量區的東西拿過來入棧,出棧等等
a =2;
b = 3;
c = a + b;
return c;
c = a +b 時會把局部變量表的a 和 b拿過來入棧,進行運算

3)動態鏈接

4)方法出口

3.特點

線程私有,它的生命周期和線程一樣 在java虛擬機規范中,對這個區域規定了兩種異常狀況:如果線程請求的棧深度大於虛擬機所允許的深度,將拋出stackoverflowerror異常;當棧在擴展時無法申請到足夠的內存,就會拋出outofmemoryerror異常

三.本地方法棧

1.定義

??本地方法棧與虛擬機棧所發揮的作用是類似的,其區別不過是虛擬機棧為虛擬機執行java方法(也就是字節碼)服務,而本地方法棧則是為虛擬機使用到的native方法服務。

四.java堆

1.定義

??對於大多數應用來說,java堆是java虛擬機所管理的內存中最大的一塊。java堆是被所有線程共享的一塊內存區域,在虛擬機啟動時創建。此內存區域的唯一目的是存放對象實例,幾乎所有的對象實例都在這裡分配內存。

??java堆是垃圾回收器管理的主要區域,因此很多時候也被稱為“GC堆”,如果從內存回收的角度看,由於現在收集器基本都是采用的分代收集算法,所以java堆中還可以細分為:新生代和老生代;再細致一點的有Eden空間,From Survivor空間、To Survivor空間等。不過無論如何劃分,都與存放內容無關,無論哪個區域,存儲的都仍然是對象實例,進一步劃分的目的是為了更好的回收內存,或者更快的分配內存。

2.特點

java堆可以處於物理上不連續的內存空間中,只要邏輯上是連續的即可。 當在堆中沒有內存完成實例的分配,並且堆也無法再擴展時,將會拋出outofmemoryerror異常。

五.方法區

1.定義

??是各個線程共享的內存區域,它用於存放已經被虛擬機加載的類信息、常量、靜態變量、即時編譯器編譯後的代碼等數據。它有一個別名NonHeap(非堆),目的應該是與java堆區分開來。方法區的大小決定了系統可以保存多少個類。

??運行時常量池是方法區的一部分。Class文件中除了有類的版本、字段,方法、接口等信息外,還有一項信息是常量池,用於存放編譯期生成的各種字面量和符號引用,這部分內容將在類加載後存放到方法區的運行時常量池中。

常量池之中主要存放兩大類常量:字面量、符號引用。字面量比較接近於java語言層面的常量概念,如文本字符串、被聲明為final的常量值等。而符號引用則屬於編譯原理方面的概念,包括下面三類常量:
- 類和接口的全限定名
- 字段的名稱和描述符
- 方法的名稱和描述符

被更新了,自己之前一直以為只有字面量

\

2.特點

各個線程共享的內存區域 垃圾回收再這個區域比較少出現,這個區域的內存回收目標主要是針對常量池的回收和對類型的卸載,一般來說這個區域的回收成績比較難以令人滿意,尤其是類型的卸載,條件相當苛刻,但是這部分區域的回收確實是必要的 根據java虛擬機規范,當方法區無法滿足內存分配時,將拋出outofmemoryerror異常

六.直接內存

1.定義

??直接內存並不是虛擬機運行時數據區的一部分,也不是java虛擬機規范中定義的內存區域。但是該部分內存在被頻繁的使用,而且也可能導致oom異常出現。

??在jdk1.4中新加入了NIO類,引入了一種基於通道(channel)與緩沖區(buffer)的I/O方式,它可以使用native函數庫直接分配堆外內存,然後通過一個存儲在java堆中的DirectByteBuffer對象為這塊內存的引用進行操作。這樣能在一些場景中顯著提高性能,因為避免了在java堆和native堆中來回復制數據。

??顯然,本機直接內存的分配不會受到java堆大小的限制,但是受限於本機總內存的大小,同樣會產生OOM。

六.對比

這裡寫圖片描述

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved