1. 程式人生 > >Java -----JVM運行時數據區

Java -----JVM運行時數據區

res 方法 靜態變量 存儲方式 ati mage spa 堆區 play

一、JVM體系結構

想要了解運行時數據區,先關註一下JVM的體系結構,知道數據區在JVM的整體位置和作用。

技術分享

二、JVM運行時數據區

1.程序計數器

一塊較小的內存空間,它是當前線程所執行的字節碼的行號指示器,字節碼解釋器工作時通過改變該計數器的值來選擇下一條需要執行的字節碼指令,分支、跳轉、循環等基礎功能都要依賴它來實現。每條線程都有一個獨立的的程序計數器,各線程間的計數器互不影響,因此該區域是線程私有的。

當線程在執行一個Java方法時,該計數器記錄的是正在執行的虛擬機字節碼指令的地址,當線程在執行的是Native方法(調用本地操作系統方法)時,該計數器的值為空。另外,該內存區域是唯一一個在Java虛擬機規範中沒有規定任何OOM(內存溢出:OutOfMemoryError)情況的區域。

2.Java虛擬機棧—JVM Stacks

JVM棧是線程私有的,每個線程創建的同時都會創建JVM棧,java虛擬機對Java棧的兩種操作:以幀為單位的壓棧和彈棧。

每當線程調用一個Java方法是,虛擬機都會在該線程的Java棧中亞茹一個新的棧幀。而這個棧幀存儲著該方法的參數,局部變量,中間運算結果等等數據。

棧幀

由三部分組成:局部變量、操作數棧和幀數據區

局部變量:包含對應方法的參數和局部變量,局部變量區是以字長為單位存儲數據的,並且是一個從0開始計數的數組空間,數據類型int 、float、對象的引用reference和returnAddress被存儲在一個存儲空間,而類型byte、short和char的值存入數組前都會被轉換成int值。一次也是占據一個存儲空間,long和double在數組中占據連續的兩個存儲空間。

技術分享 技術分享

可以看到在0的位置會存儲一個隱含的變量this,用老表示調用該方法的對象本身。

技術分享 技術分享

而類方法並沒有this,因為類方法只與類相關。而與具體的對象無關。

操作數棧

虛擬機在操作數棧中存儲的是方法運算的操作數和運算結果,操作方式是壓棧和出棧,數據的存儲方式和上面說的局部變量存儲方式是一樣的。

Java虛擬機中國是沒有寄存器的,這也是符合JVM平臺無關特性的一點,虛擬機把操作數棧作為他的工作區,大多數指令都會從這裏彈出數據,執行運算,然後再把結果壓回操作數棧

幀數據區

Java棧幀還需要一些數據來支持常量池解析、正常方法返回以及異常派發機制,這些信息都被保存在Java棧幀的幀數據區中

3.本地方法棧(Native Method Stacks)

該區域與虛擬機棧所發揮的作用非常相似,只是虛擬機棧為虛擬機執行Java方法服務,而本地方法棧則為使用到的本地操作系統(Native)方法服務。

4.Java堆(Java Heap)

它是JVM用來存儲對象實例以及數組值的區域,可以認為Java中所有通過new創建的對象的內存都在此分配,Heap中的對象的內存需要等待GC進行回收。

5.方法區域(Method Area)

方法區在JVM中也是一個非常重要的區域,它與堆一樣,是被線程共享的區域。在方法區中,存儲了每個類的信息(包括類的名稱、方法信息、字段信息)、靜態變量、常量以及編譯器編譯後的代碼等。

  在Class文件中除了類的字段、方法、接口等描述信息外,還有一項信息是常量池,用來存儲編譯期間生成的字面量和符號引用。

 在方法區中有一個非常重要的部分就是運行時常量池,它是每一個類或接口的常量池的運行時表示形式,在類和接口被加載到JVM後,對應的運行時常量池就被創建出來。當然並非Class文件常量池中的內容才能進入運行時常量池,在運行期間也可將新的常量放入運行時常量池中,比如String的intern方法。

在JVM規範中,沒有強制要求方法區必須實現垃圾回收。很多人習慣將方法區稱為“永久代”,是因為HotSpot虛擬機以永久代來實現方法區,從而JVM的垃圾收集器可以像管理堆區一樣管理這部分區域,從而不需要專門為這部分設計垃圾回收機制。不過自從JDK7之後,Hotspot虛擬機便將運行時常量池從永久代移除了。

總結:

技術分享

Java -----JVM運行時數據區