《深入理解 Java 虛擬機》學習筆記2

《深入理解 Java 虛擬機》學習筆記2

第2章 Java 內存區域與內存溢出異常

2.1 概述

2.2.1 程序計數器

  1. 程序計數器(Program Counter Register)
  2. java 虛擬機的多線程是通過線程輪流切換並分配處理器執行時間來實現的,在任何一個確定額時刻,一個處理器(對於多核來說是一個內核)都只會執行一條線程中的指令。因此,爲了線程切換後可以恢復到正確的執行位置,每條線程需要一個獨立的程序計數器,各條線程之間的計數器互不影響,獨立存儲。
  3. 如果線程正在執行的是一個 Java 方法,則計數器記錄的是正在執行的虛擬機字節碼指向的地址;如果執行的是 Native 方法,這個計數器爲空(Undefined)。

2.2.2 Java 虛擬機棧

  1. Java 虛擬機棧(Java Virtual Machine Stack)是線程私有的,它的生命週期與線程相同。
  2. Java 虛擬機棧描述的是 Java 方法執行的內存模型:每個方法在執行的同時都會創建一個棧幀(Stack Frame)用於存儲局部變量表,操作數棧,動態鏈接,方法出口等信息。每一個方法從調用到執行完畢的過程,對應着一個棧幀咋即虛擬機棧中入棧到出棧的過程。
  3. Java 中的『棧』往往指的就是虛擬機棧,或者說是『虛擬機棧中的局部變量表』。局部變量表包含:基本數據類型(boolean, byte, char, short, int, float, long, double) + 對象引用(reference)+ returnAddress
  4. 局部變量表所需的空間在編譯期間完成,當進入一個方法時,這個空間往往是一定的。
  5. 在 Java 虛擬機規範中,在這個區域定義了兩種異常狀況:
    1. 如果線程請求的棧深度大於虛擬機所允許的深度,將拋出 StackOverflowError 異常。
    2. 如果虛擬機棧可以動態擴展,如果擴展時無法申請到足夠的內存,拋出 OutOfMemoryError 異常。

2.2.3 本地方法棧

  1. 本地方法棧(Java Native Method Stack)類似虛擬機棧,不過虛擬機棧是爲 Java 方法服務,本地方法棧爲 Native 方法服務。

2.2.4 Java 堆

  1. 對於大多數應用來說,Java 堆(Java Heap)是 Java 虛擬機所管理的內存中最大的一塊。Java 堆是被所有線程共享的一塊內存區域,在虛擬機啓動時創建。此內存區域的唯一目的就是存放對象實例,幾乎所有的對象實例都是在這裏分配的內存。
  2. Java 堆是垃圾收集器管理的主要區域,因此很多時候也被稱爲『GC堆(Garbage Collected Heap)』
  3. Java 堆可以是物理上不連續的,只要邏輯上連續即可,就像我們的磁盤一樣。如果堆滿了,無法繼續進行擴展,會報錯 OutOfMemoryError 異常。

2.2.5 方法區

  1. 方法區(Method Area)與 Java 一樣,是各個線程共享的內存區域,它用於存儲已被虛擬機加載的類信息,常量,靜態變量,即時編譯器編譯後的代碼等數據。

2.2.6 運行時常量池

  1. 運行時常量池(Runtime Constant Pool)是方法區的一部分。用於存放編譯期生成的各種字面量和符號引用,這部分內容將在類加載後進入方法區的運行時常量池中存放。
  2. Java 虛擬機對 Class 文件的每一部分的格式都有嚴格的規定,每一個字節用於存儲哪種數據都必須符合規範上的要求才會被虛擬機認可,裝載和執行。
  3. 運行時常量池相對於 Class 文件常量池的另外一個重要特徵就是具備動態性Java 語言並不要求常量一定只有編譯期才能產生,運行期間也可能將新的常量放入池。這種特性被開發人員用的較多的是 String 的 intern() 方法。

2.2.7 直接內存

  1. 直接內存(Direct Memory)並不是虛擬機運行時數據區的一部分,也不是 Java 虛擬機規範中定義的內存區域。在 JDK1.4 中引入 NIO(New Input/Output)類,引入一種基於通道(Channel)與緩衝區(Buffer)的 I/O 方式,它可以使用 Native 函數庫直接分配堆外內存,然後通過一個存儲在 Java 堆中的 DirectByteBuffer 對象作爲這塊內存的引用進行操作。

2.3 HotSpot 虛擬機對象探祕

2.3.1 對象的創建

  1. 虛擬機遇到一條 new 指令時,首先將去檢查這個指令的參數是否能在常量池中定位到一個類的符號引用,並且檢查這個符號引用代表的類是否已經被加載,解析和初始化過。如果沒有,必須先執行 相應類的加載過程
  2. 類加載檢查通過後,虛擬機爲新生對象分配內存。對象所需內存的大小在類加載完後可以完全確定,爲對象分配空間的任務等同於把一塊確定大小的內存從 Java 堆中劃分出來。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章