JVM運行時的數據區

jopen 10年前發布 | 12K 次閱讀 JVM Java開發

理解JVM運行時的數據區是Java編程中的進階部分。我們在開發中都遇到過一個很頭疼的問題就是OutOfMemoryError(內存溢出 錯誤),但是如果我們了解JVM的內部實現和其運行時的數據區的工作機制,那么前面的問題就會迎刃而解。在這片文章中,我們將簡單了解JVM中有哪些運行 時數據區以及這些數據區的工作機制。

JVM運行時數據區分類

  • 程序計數器 (Program Counter (PC) Register)
  • JVM棧 (Java Virtual Machine Stacks)
  • 堆內存 (Heap Memory)
  • 方法區 (Method Area)
  • 運行時常量池 (Run-time Constant Pool)
  • 本地方法棧 (Native Method Stacks)

有圖才能說

JVM運行時的數據區

按線程持有劃分

查看上面的圖,可以得知以上六個數據區其實線程私有還是共享,可以分為如下兩種。

  • 單個線程私有 (Managed Per-Thread) 屬于這一種的數據區包含 程序計數器, JVM棧還有本地方法棧。 每個線程都私有這三個數據區,這些數據區在其所屬的線程創建時初始化,并隨著所屬線程結束被銷毀。
  • 多個線程共享 屬于這一種的數據區包含 堆內存,方法區和運行時常量池。這些數據區可以被每一個線程訪問,他們隨著JVM啟動而初始化,同時伴隨JVM關閉而銷毀。

程序計數器

在通用的計算機體系中,程序計數器用來記錄當前正在執行的指令,在JVM中也是如此。程序計數器是線程私有,所以當一個新的線程創建時,程序計數器 也會創建。由于Java是支持多線程,Java中的程序計數器用來記錄當前線程中正在執行的指令。如果當前正在執行的方法是本地方法,那么此刻程序計數器 的值為undefined 。注意這個區域是唯一一個不拋出OutOfMemoryError的運行時數據區。

JVM棧

在介紹JVM棧之前,簡單介紹一個概念,棧幀

棧幀

一個棧幀隨著一個方法的調用開始而創建,這個方法調用完成而銷毀。棧幀內存放者方法中的局部變量,操作數棧等數據。

JVM棧只對棧幀進行存儲,壓棧和出棧操作。棧內存的大小可以有兩種設置,固定值和根據線程需要動態增長。在JVM棧這個數據區可能會發生拋出兩種錯誤。

  • StackOverflowError 出現在棧內存設置成固定值的時候,當程序執行需要的棧內存超過設定的固定值會拋出這個錯誤。
  • OutOfMemoryError 出現在棧內存設置成動態增長的時候,當JVM嘗試申請的內存大小超過了其可用內存時會拋出這個錯誤。

堆數據區

堆數據區是用來存放對象和數組(特殊的對象)。堆內存由多個線程共享。堆內存隨著JVM啟動而創建。眾所周知,Java中有一個很好的特性就是自動 垃圾回收。垃圾回收就操作這個數據區來回收對象進而釋放內存。如果堆內存剩余的內存不足以滿足于對象創建,JVM會拋出OutOfMemoryError 錯誤。

方法區

在JVM規范中,方法區被視為堆內存的一個邏輯部分。這一點可能由于具體的JVM實現而不同,甚至在方法區不實現垃圾回收處理也是可以的。方法區和 堆內存一樣被多個線程訪問,方法區中存放類的信息,比如類加載器引用,屬性,方法代碼和構造方法和常量等。當方法區的可用內存無法滿足內存分配需求 時,JVM會拋出OutOfMemoryError錯誤。

運行時常量池

運行時常量池創建在方法區,當一個類或者一個接口被創建的時候,JVM會創建一個運行時常量池。一個運行時常量池實際上是一個類或者接口的 class文件中常量池表(constant_pool table)的運行時展示形式。一個運行時常量池包含了多種類型的常量,從諸如運行時可以確定的數值型字面量到運行時才能決定的方法和屬性引用。當運行時 常量池無法滿足于內存分配需求時,JVM會拋出OutOfMemoryError錯誤。

本地方法棧

一個支持native方法調用的JVM實現,需要有這樣一個數據區,就是本地方法棧,Java官方對于本地方法的定義為methods written in a language other than the Java programming language,就是使用非Java語言實現的方法,但是通常我們指的一般為C或者C++,因此這個棧也有著C棧 這一稱號。一個不支持本地方法執行的JVM沒有必要實現這個數據區域。本地方法棧基本和JVM棧一樣,其大小也是可以設置為固定值或者動態增加,因此也會對應拋出StackOverflowError和OutOfMemoryError錯誤。

譯文信息

注:本文介紹JVM運行時數據相對比較概括,以后會有更加詳細的針對單個數據區的介紹。

原文鏈接: http://droidyue.com/blog/2014/12/21/java-runtime-data-areas/

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