1. 程式人生 > >部分筆記—Java記憶體區域與記憶體溢位異常

部分筆記—Java記憶體區域與記憶體溢位異常

Java與c++記憶體管理對比

  • C或C++
    在記憶體管理區域,即擁有每一個物件的“所有權”,又擔負者每一個物件生命開始到終結的責任
  • Java
    在虛擬機器自動記憶體管理機制的幫助下,不再需要為每一個new操作去寫配對的delete/free程式碼,不容易出現記憶體洩漏和記憶體溢位問題,由虛擬機器管理記憶體。

執行時資料區域

Java虛擬機器在執行java程式的過程中會把它所管理的記憶體劃分為若干個資料區域。
【(方法區、堆)(所有執行緒共享區域),(虛擬機器棧、本地方法棧、程式計數器)(執行緒隔離資料區)】

程式計數器

可當做當前執行緒所執行的位元組碼的行號指示器。在虛擬機器概念模型中,位元組碼直譯器工作時就是通過改變程式計數器的值來選取下一條需要執行的位元組碼指令,分支、迴圈、跳轉、異常處理、執行緒恢復等基礎功能都需要依賴該計數器。
為了執行緒切換後能恢復到正確的執行位置,每條執行緒都需要一個獨立的程式計數器,各條執行緒之間計數器互不影響,獨立儲存,稱該記憶體區域為“執行緒私有”

的記憶體。
若執行緒正在執行的是一個Java方法,則計數器記錄的是正在執行的虛擬機器位元組碼指令的地址。如果是Native方法,計數器為空(Undefine)

Java虛擬機器棧

執行緒私有,生命週期與執行緒相同。每個方法在執行的同時都會建立一個棧幀(Stack Frame)用於儲存區域性變量表運算元棧動態連結方法出口等資訊。每個方法從呼叫直至執行完成的過程,就對應一個棧幀在虛擬機器棧中入棧到出棧的過程。
區域性變量表,存放了編譯期可知的所有基本資料型別、物件引用和returnAddress型別(指向一條位元組碼指令地址)
在Java虛擬機器規範中,對該區域規定了兩種異常狀況:
* 如果執行緒請求的棧深度大於虛擬機器所允許的深度,將丟擲StackOverflowError

異常;
* 如果虛擬機器棧可以動態擴充套件,如果擴充套件時無法申請到足夠的記憶體,將丟擲OutOfMemoryError異常。

本地方法棧

作用與虛擬機器棧類似,之間的區別: 虛擬機器棧為虛擬機器執行Java方法(也就是位元組碼)服務,而本地方法棧則為虛擬機器使用到的Native方法服務。本地方法棧也會丟擲StackOverflowError異常和OutOfMemoryError異常。

Java堆

  • 是Java虛擬機器所管理的記憶體中的最大一塊
  • 所有執行緒共享
  • 此記憶體區域的唯一目的就是存放物件例項,幾乎所有的物件例項都在這裡分配記憶體

Java堆為垃圾收集器管理的主要區域,又稱GC堆。Java堆可以處於物理上不連續的記憶體空間中,只要邏輯連續即可。即可實現成固定大小的,也可以是可擴充套件的,主流虛擬機器都是可擴充套件的(用過-Xms與-Xmx控制)。如果堆中沒有記憶體完成例項分配,並且堆無法擴充套件時,將丟擲OutOfMemoryError異常。

方法區

與Java堆一樣,是各個執行緒共享區域,儲存虛擬機器載入的類資訊、常量、靜態變數、即時編譯器編譯後的程式碼等資料。別名Non-Heap
Java虛擬機器規範對方法區限制很寬鬆,除了和Java堆一樣,不需要連續的記憶體和可選擇固定大小或者可擴充套件外,還可以選擇不實現垃圾收集。相對而言,垃圾收集行為在這個區域是比較少出現的,但非資料進入方法區就像“永久代”的名字一樣可以永久存在了,這區域的記憶體回收目標主要是針對常量池的回收和對型別的解除安裝。
Java虛擬機器規範規定,當方法區無法滿足記憶體分配需求時,將丟擲OutOfMemoryError異常。

執行時常量池

屬方法區的一部分,Class檔案中除了有類的版本、欄位、方法、介面等描述資訊外,還有一項資訊就是常量池(Constant Pool Table),用於存放編譯器生成的各種字面量和符號引用,這部分記憶體將在類載入後進入方法區的執行時常量池中存放。
Java對Class檔案的每個部分(包括常量池)的格式有明確規定,每一個位元組用於儲存哪種資料都必須符合規範上的要求才會被虛擬機器認可、裝載和執行,但對於執行時常量池,Java虛擬規範則沒做任何細節要求。
執行時常量池相對於Class檔案常量池的另一個重要特徵是具備動態性,Java語言並不要求常量一定只有編譯期才能產生。執行期間也可以把新的常量放在執行時常量池中。
跟方法區一樣會丟擲OOM.

物件的建立流程

1、虛擬機器遇到一個new指令,首先去檢查指令引數是否能在常量池中定位到一個類的符號引用,並檢查這個符號引用代表的類是否被載入、解析和初始化過。
2、在類載入檢查過後,接下來虛擬機器為新生物件分配記憶體,物件所需記憶體的大小在類載入完成後便可完全確定,為物件分配控制元件的任務等同於把一塊確定大小的記憶體從Java堆中劃分出來。(“指標碰撞”,“空閒列表”,TLAB(Thread Local Allocation Buffer))
3、記憶體分配完後,虛擬機器需要將分配到的記憶體空間都初始化為0值(不包括物件頭)
4、接下來,虛擬機器要對物件進行必要的設定,例如這個物件是哪個類的例項、如何才能找到類的元資料資訊、物件的雜湊碼、物件的GC分代年齡等資訊。
5、上面工作完成後,從虛擬機器的視角來看,一個新的物件已經產生,但從Java程式來看,物件建立才剛剛開始,<init>方法還沒有執行,所有欄位都還為零。執行完new指令後還會接著執行方法,把物件按照程式設計師的意願初始化,這樣一個真正可用的物件才算完全產生出來。

物件的記憶體佈局

在HotSpot虛擬機器中,物件在記憶體中的佈局可以分為3部分:物件頭、例項資料和對齊填充

物件頭

物件頭包含兩個部分資訊:
一部分為儲存物件自身的執行時的資料,如雜湊碼、GC分代年齡、鎖狀態標識、執行緒特有的鎖、偏向執行緒的ID、偏向時間戳。該資料長度在32位和64為虛擬機器中分別為32bit和64bit。
另外一部分為型別指標,即物件指向它的類元資料的指標,虛擬機器通過該指標來確定這個物件是哪個類的例項。若物件是個資料,則物件頭還有一部分為陣列長度。

例項資料

是物件真正儲存的有效資訊,也是在程式程式碼中所定義的各種型別的欄位內容。無論是從父類繼承下來的,還是在子類中定義的,都需要記錄下來。

對齊填充

僅僅起佔位符的作用。因為HotSpot虛擬機器的自動記憶體管理系統要求物件的起始地址必須是8的整數倍。也就是物件的大小是8的整數倍。而物件頭正好是8的整數倍,因此,當物件例項資料部分沒有對齊時,就需要通過對齊填充來補齊。

物件的訪問定位

為了使用物件,Java程式需要從棧上的reference資料來操作堆上的具體物件。而主流的訪問方式有兩種,使用控制代碼訪問和直接指標訪問。
這裡寫圖片描述

這裡寫圖片描述

  • 通過控制代碼訪問最大的好處就是reference中儲存的是穩定的控制代碼地址,在物件被移動時只會改變控制代碼資料中的例項資料指標,而reference本身不需要修改。
  • 使用直接指標訪問最大的好處就是速度快,節省了一次指標定位的時間開銷。

對於Hotspot VM而言,虛擬機器使用的是直接指標訪問。

相關推薦

部分筆記Java記憶體區域記憶體溢位異常

Java與c++記憶體管理對比 C或C++ 在記憶體管理區域,即擁有每一個物件的“所有權”,又擔負者每一個物件生命開始到終結的責任 Java 在虛擬機器自動記憶體管理機制的幫助下,不再需要為每一個new操作去寫配對的delete/free程式碼,不容易出

學習筆記1:深入理解Java虛擬機器——JVM高階特性最佳實踐_走進java_java記憶體區域記憶體溢位異常

第一部分:走進java Java虛擬機器 程式碼在華章下載 jdk釋出了六個命令列工具和兩個視覺化故障處理工具。 推薦書籍 設計原本 領域特定語言 現在著名的Java虛擬機器 hotspot vm(預設) jrockit vm j9 vm jdk sun jdk op

《深入理解java虛擬機器》讀書筆記(二)---- Java記憶體區域記憶體溢位異常

執行時資料區域 java虛擬機器所管理的記憶體將會包括以下幾個執行時資料區域: 1、程式計數器 程式計數器是一塊較小的記憶體空間,它可以看作是當前執行緒所執行位元組碼的行號指示器。在虛擬機器的概念模型裡,位元組碼直譯器的工作就是通過改變這個計數器的值來選取下一條需要執

Java虛擬機器筆記-1(Java技術體系&自動記憶體管理機制&記憶體區域記憶體溢位&垃圾收集器記憶體分配策略)

世界上沒有完美的程式,但寫程式是不斷追求完美的過程。 Devices(裝置、裝置)、GlassFish(商業相容應用伺服器) 目錄 1. Java技術體系包括: Java技術體系的4個平臺 虛擬機器分類 HotSpot VM 模組化、混合程式設計 多核並行

Java記憶體區域記憶體溢位異常 JVM筆記1

目錄 執行時資料區域 程式計數器 虛擬機器棧 本地方法棧 堆 方法區 直接記憶體 物件的記憶體佈局 物件頭 例項資料 對齊填充 物件的訪問定位 執行時資料區域 JAVA虛擬機器在執行Java程式的過程中會把它所管理的記憶體劃分為若干個不同的

《JVM筆記》之一:Java記憶體區域記憶體溢位異常

Java與C++之間有一堵由記憶體動態分配和垃圾收集技術所圍成的高牆,牆外面的人想進去,牆裡面的人卻想出來。 按照《Java虛擬機器規範(第2版)》的規定,Java虛擬機器所管理的記憶體將包括以下幾個執行時資料區域,來個圖更加直觀點,如下圖所示:   解釋下各個部分 程式計數器: Program Coun

筆記二(自動記憶體管理機制)-Java記憶體區域記憶體溢位異常

1 執行時資料區域      Java虛擬機器在執行Java程式的過程中會把它所管理的記憶體劃分為若干個不同的資料區域。這些區域都有各自的用途,以及建立和銷燬的時間,有的區域隨著虛擬機器程序的啟動而存在,有些區域則是依賴使用者執行緒的啟動和結束而建立和銷燬。1.1 程式計數器

《深入理解Java虛擬機器》讀書筆記:第二章Java記憶體區域記憶體溢位異常

Java虛擬機器在執行Java程式的過程中會把它所管理的記憶體劃分為若干個不同的資料區域:方法區、虛擬機器棧、本地方法棧、堆、程式計數器 程式計數器(ProgramCounterRegister):一塊較小的記憶體空間,看作當前執行緒所執行的位元組碼的行號指示器;位元組碼

深入Java虛擬機器筆記(一):Java記憶體區域記憶體溢位異常

1、程式計數器為很小的記憶體空間,為當前執行緒執行的位元組碼的行號指示器,通過改變計數器的值來選取下一條需要執行的位元組碼指令,迴圈、分支等基礎功能都是需要計數器來完成的 2、Java虛擬機器棧為Java方法執行的記憶體模型,每個方法被執行時都會同時建立棧

筆記:深入理解JVM 第2章 Java記憶體區域記憶體溢位

1、JVM 執行時資料區 所有執行緒共享的資料區:方法區(持久代)、堆區 執行緒隔離的資料區:程式計數器、Java虛擬機器棧區 堆區構成:新生代 ( 由Eden, From Survivor, To Survivor 構成)、老生代 執行時常量池:方法區一部分,用於存放編

java記憶體區域記憶體溢位異常學習筆記

一,java記憶體區域與記憶體溢位異常java執行時資料區域1,程式計數器:     程式計數器(program counter register)是一塊較小的記憶體空間,它可以看作是當前執行緒所執行的位元組碼的行號指示器。在虛擬機器的概念模型裡(僅是概念模型,各種虛擬可能會

《深入理解 Java 虛擬機器》讀書筆記Java 記憶體區域記憶體溢位異常

前言 最近開始看這本書,記得前段時間拿起這本書的時候,心情是相當沉重的!當時的劇本是這樣的—— 內景。家裡 - 下午 我(畫外):唉,有點無聊啊!(偶然撇過書架)這麼多書得看到什麼時候啊,要不要拿一本翻翻呢?但是在家裡好像有點看不下去啊,是太安逸了嗎?最近那本《圖解 HTTP》也還沒看完,感覺暫時有點不想

java虛擬機器—-java記憶體區域記憶體溢位異常

一,java虛擬機器所管理的執行時資料區域分為:程式計數器、java虛擬機器棧、本地方法棧、java堆、方法區、執行時常量池。                     1,程式計數器:

《深入理解Java虛擬機器—JVM高階特性實踐 周志明 著》之第2章 Java記憶體區域記憶體溢位異常

1、Java虛擬機器所管理的記憶體包括以下幾個執行時資料區域: 2、程式計數器:          1. 可以看作是當前執行緒所執行的位元組碼的行號指示器,是一塊較小的記憶體空間;  &nbs

JAVA虛擬機器(JVM)劃重點 第二章 Java記憶體區域記憶體溢位異常 之 虛擬機器物件

本部落格參考《深入理解Java虛擬機器》(第二版)一書,提取重點知識,再加以個人的理解編寫而成。轉載請標明來源。 JAVA虛擬機器(JVM)劃重點 第二章 Java記憶體區域與記憶體溢位異常 之 虛擬機器物件 Java物件的建立 1、類載入過程

JAVA虛擬機器(JVM)劃重點 第二章 Java記憶體區域記憶體溢位異常 之 執行時資料區域

本部落格參考《深入理解Java虛擬機器》(第二版)一書,提取重點知識,再加以個人的理解編寫而成。轉載請標明來源。 JVM劃重點 第二章 Java記憶體區域與記憶體溢位異常 之 執行時資料區域 概述 執行時資料區域 程式計數器 Java虛擬機

JVM-Java記憶體區域記憶體溢位

JVM虛擬機器執行時資料區結構分為:      其中方法區和堆是所有執行緒共享的記憶體區域,而Java棧、本地方法棧、程式計數器是執行緒私有的。 我們詳細介紹執行時資料區的各個區域及其作用。  程式計數器:   一塊較小的記憶體空間,位元組碼指示器工作時通過改變計數器的值來選取下一條需

Java記憶體區域記憶體溢位

記憶體區域     Java虛擬機器在執行Java程式的過程中會把他所管理的記憶體劃分為若干個不同的資料區域。Java虛擬機器規範將JVM所管理的記憶體分為以下幾個執行時資料區:程式計數器、Java虛擬機器棧、本地方法棧、Java堆、方法區。下面詳細闡述各

虛擬機器學習之一:java記憶體區域記憶體溢位異常

1.執行時資料區域 java虛擬機器在執行java程式的過程中會把它所管理的記憶體劃分為若干個不同的資料區域。這些區域都有各自的用途和建立、銷燬時間,有的區域伴隨虛擬機器程序的啟動而存在,有些區域則依賴使用者執行緒的啟動和結束而建立和銷燬。 1.1程式計數器 程式計數器

java記憶體區域記憶體溢位異常

執行是記憶體區域 java虛擬機器在執行java程式的過程中會把它所管理的記憶體劃分為若干個不同的資料區域。 1.執行緒獨有的記憶體區域 (1)程式計數器(Program Counter Register) 這塊記憶體區域很小,它是當前執行緒所執行的位元組碼的行號