深入理解java虛擬機(二):Java內存區域與內存溢出異常

運行時數據區域

java虛擬機所管理的內存包括以下幾個運行時數據區域

一、程序計數器

程序計數器是一塊較小的內存空間,它可以看做當前線程所執行的字節碼的行號指示器。在虛擬機的概念模型中,字節碼解釋器工作時就是通過改變這個計數器的值來選擇下一條需要執行的字節碼指令。

java虛擬機的多線程是通過線程線程輪流切換並分配處理器執行時間的方式來實現的,在任何一個確定的時刻,一個處理器都只會執行一條線程中的指令,因此爲了線程切換後能恢復到正確的執行位置,每條線程都需要有一個獨立的程序計數器,各條線程之間的計數器互不影響,獨立存儲。我們稱這類內存區域爲線程私有的內存。

如果正在執行java方法,這個計數器記錄的是正在執行的虛擬機字節碼指令的地址,如果正在執行的是Native方法,這個計數器的值爲null。此內存區域是唯一一個在java虛擬機規範中沒有規定任何OutOfMemoryError情況的區域

二、java虛擬機棧(Java Virtual Machine Stacks)

與程序計數器一樣 ,虛擬機棧也是線程私有的,它的生命週期與線程相同

虛擬機棧描述的是Java方法執行的內存模型。

  1. 每個方法在執行的同時都會創建一個棧幀(Stack Frame)。用於存儲局部變量表、操作數棧、動態鏈接、方法出口等。方法從調用到執行完成的過程,就對應着一個棧幀在虛擬機中從入棧到出棧的過程。
  2. 局部變量表:存放了編譯器可知的各種基本數據類型(特殊的:對象引用—reference類型,不同於對象本身,可能是一個指向對象起始位置的引用指針,也可能是指向一個代表對象的句柄或其他與此對象相關的位置;returnAddress類型:執行一條字節碼指令的地址)
  3. 64位長度的long和 double類型的數據會佔用兩個局部變量空間(Slot),其餘的數據類型佔用一個。局部變量表所需內存空間在編譯期間完成分配,在方法運行期間不會改變局部變量表的大小
  4. 會拋出StackOverflowError和OutOfMemoryError

三、本地方法

類似於虛擬機棧

區別:

  • 在於虛擬機棧爲虛擬機執行java方法服務;
  • 本地方法棧則爲虛擬機使用的Native方法服務;
  • 有些虛擬機直接將本地方法棧和虛擬機棧合二爲一

四、Java堆(Java Heap)

堆是Java虛擬機管理的內存中最大的一塊,被所有線程共享在虛擬機啓動時創建。堆的唯一目的是存放對象實例,幾乎所有的對象實例都在這裏分配內存(Java虛擬機規範描述的是:所有的對象實例以及數組都要在堆上分配),但是隨着JIT編譯器的發展和逃逸技術逐漸成熟,棧上分配,標量替換優化技術等使得所有的對象都分配在堆上變得不是那麼絕對了。

Java堆是垃圾收集器管理的主要區域,又稱爲GC堆。從內存回收的角度看,由於現在收集器基本都採用分代收集算法,所以Java堆還可以細分爲:

  • 新生代
  • 老年代

從內存分配的角度來看,線程共享的Java堆中可能劃分出多個線程私有的分配緩衝區

Java虛擬機規範規定:Java堆可以處於物理上不連續的內存空間中,只要邏輯上連續即可

五、方法區

方法區與Java堆一樣,是各個線程共享的內存區域,它用於存儲已被虛擬機加載的

  • 類信息
  • 常量
  • 靜態常量
  • 即時編譯器編譯後的代碼

使用HotSpot虛擬機的開發者更願意將把方法區稱爲永久代,是因爲HotSpot設計團隊選擇把GC分代收集拓展到方法區,或者說使用永久代來實現方法區。

六 、運行時常量池

運行時常量池是方法區的一部分。Class文件中除了有類的版本、字段、方法、接口等描述信息外,還有一項信息常量池(Constant Pool Table),用於存放編譯期生成的各種字面量和符號引用,這部分內容在類加載後進入方法區的運行時常量池中存放。一般來說,還會把翻譯過來的直接引用也存儲在運行時常量池中。

運行時常量池相對於Class文件常量池的另外一個重要特徵是具備動態性。運行期也可能將新的常量放入池中,利用的比較多的是String類的intern()方法

七、直接內存

直接內存並不是虛擬機運行時數據區的一部分,也不是Java虛擬機規範中定義的內存區域

JDK1.4中新加入的NIO,引入了一種基於通道與緩衝區的I/O方式,它可以使用Native函數庫直接分配堆外內存,然後通過一個存儲在Java堆中的DirectByteBuffer對象作爲這塊內存的引用進行操作,這樣能在一些場景中顯著提高性能,因爲避免了java堆和Native堆中來回複製數據。

本機直接內存的分配不會受到Java堆大小的限制,但會受到本機總內存的限制。需要注意在分配內存時不要忽略直接內存。

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