JVM 體系結構

dbww4269 8年前發布 | 7K 次閱讀 JVM Java開發

JVM 體系結構分為三部分:1. 類加載器(ClassLoader):用于裝載 .class 文件 2. 執行引擎:用于執行字節碼,或者執行本地方法 3. 運行時數據區:包括方法區、堆、Java 棧、PC 寄存器、本地方法棧

JVM 體系結構分為三部分:1. 類加載器(ClassLoader):用于裝載 .class 文件

2. 執行引擎:用于執行字節碼,或者執行本地方法

3. 運行時數據區:包括方法區、堆、Java 棧、PC 寄存器、本地方法棧

程序計數器

占用很小的內存空間,可以看做是當前線程所執行的字節碼的行號指示器。

JVM 的多線程是通過線程輪流切換并分配處理器執行時間的方式來實現的,在任何一個時刻一個處理器(或多個處理器的一個內核)只會執行一個條線程的指令。程序計數器用于在線程切換后為了恢復在正確執行的位置(正在執行的字節碼指令的地址)。

每個線程都需要一個獨立的程序計數器,它的生周期與當前線程相同。

虛擬機棧

JVM 棧是線程私有的,每個線程創建的同時都會創建 JVM 棧,JVM 棧是以棧幀為數據單元。

棧幀中存放著局部變量表(Java 中定義的八種基本類型:boolean、char、byte、short、int、long、float、double 和引用類型 —— 一個指向堆上的地址)、返回地址以及操作數棧。

每一個方法被調用直至執行完成的過程,就是對于的一個棧幀在虛擬機棧中從入棧到出棧的過程。

每個線程都有一個獨立的棧,生命周期與當前線程相同。

棧幀是一個后入先出(LIFO)的棧。Sun JVM 采用基于棧(內存)的指令集來實現操作數棧,并把一些訪問最頻繁的數據放到寄存器中以提高性能(另一種基于 CPU 寄存器的指令集訪問速度快,但可移植性差)。

E.g.

int a =  100 ;

int b =  98 ;

int c = a   b;

字節指令如下;

bipush 100
 istore_1
 bipush 98
 istore_2
 iload_1
 iload_2
 iadd
 istore_3

本地方法棧

與虛擬機棧相比,本地方法棧是為虛擬機使用到的本地(Native)方法服務的。此區域用于存儲每個 Native 方法調用的狀態。Sun HotSpot 虛擬機直接把本地方法棧和虛擬機棧合二為一。

每個線程都有一個獨立的本地方法棧,生命周期與當前線程相同。

Java 虛擬機管理的最大一塊內存。Heap 是大家最為熟悉的區域,它是 JVM 用來存儲對象實例以及數值的區域,可以認為 Java 中所有通過 new 創建的對象的內存都在此分配,Heap 中的對象的內存需要等待 GC  進行回收。

堆是在同一個 JVM 中所有線程共享的,因此在其上進行對象內存的分配君需要進行枷鎖,這也導致了 new 對象的開銷是比較大的。(頻繁的創建對象會帶來 GC 增加,可采用對象池技術來優化)。

JVM 將 Heap 分為 New Generation 和 Old Generation(方法 GC)。

New Generation 稱為新生代,程序中創建的對象都將分配到新生代中,新生代又由 Eden Space 和兩塊 Survivor Space 構成,可通過 -Xmn 參數來指定其大小。

Old Generation 稱為老生代,用于存放程序中經過幾次垃圾回收還存活的對象(或者大對象),例如緩存的對象等,老生代所占用的內存大小即為 -Xmx 制定的大小減去 -Xmn 指定的大小。

方法區

方法區存放了所加載的類的信息(名稱、修飾符等)、類中的靜態變量、類中的定義為 final 類型的常量、類中 Field 信息、類中的方法信息,當在程序中通過 Class 對象中的 getName、isInterface 等方法來獲取信息時,這些數據都來源于方法區。

在 Sun JDK 中這塊區域對應的是 Permanet Generation,又稱為持久代,默認為 64M,可通過 -XX:PermSize 以及 -XX:MaxPermSize 來指定其大小。

方法區是全局共享的,在一定的條件下它會被 GC,當方法區需要使用的內存超過其允許的大小時,會拋出 OutOfMemory 的錯誤。

方法區之運行時常量池

運行時常量池用于存放編譯器生成的各種字面量和符號引用,這部分將在類加載后存放到方法區的運行時常量池中。

public class Sample {
     private int a;

     public int method() {
         int b= 0;
         a++;
         b =a ;
         return b;
     }

     public static void main(String[] args) {
         Sample s = null;
         int a = 0;
         s = new Sample();
         a = s.method();
         System.out.println(a);
    }
}

Java 對象占用

每個對象由4個域構成:

1. 對象頭,表述 Object 當前狀態的信息(普通對象占 8字節,數組占12字節)

2. 基本類型(boolean、byte 占 1字節,char、short 占 2字節,int、float 占 4字節,long、double 占 8字節。

3. 引用類型占 4字節

4. 填充物,不足8的倍數的時候,自動補齊

E.g.

一個空對象(沒有聲明任何變量)占 8字節(對象頭占 8字節)

只聲明了一個 boolean 類型變量的類,占用 16字節(對象頭占 8字節,boolean 占 1字節,填充物占 7字節)

聲明了 8個 boolean 類型變量的類,占用 16字節(對象頭占 8字節,boolean 占 1字節 * 8

 

來自:http://www.androidchina.net/5774.html

 

 本文由用戶 dbww4269 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!