第2章-Java記憶體區域與記憶體溢位異常
Java記憶體區域與記憶體溢位異常
概述
對於Java程式設計師來說,在虛擬機器自動記憶體管理機制的幫助下,不再需要為每一個new操作去寫配對的delete/free程式碼,不容易出現記憶體洩漏和記憶體溢位問題,由虛擬機器管理記憶體。
執行時資料區域
Java虛擬機器在執行Java程式的過程中會把所管理的記憶體劃分為若干個不同的資料區域:
執行時資料區包括:
方法區
虛擬機器棧
本地方法棧
堆
程式計數器
1、程式計數器
一塊較小的記憶體空間,可以看作是當前執行緒所執行的位元組碼的行號指示器;執行緒隔離的記憶體區域,也稱“執行緒私有”。
執行緒正在執行一個Java方法,指向的是虛擬機器位元組碼指令的地址;正在執行的是
唯一一個在Java虛擬機器規範中沒有規定任何OutOfMemoryError情況的區域。
2、Java虛擬機器棧
執行緒私有的,他的生命週期與執行緒相同。虛擬機器棧描述的是Java方法執行的記憶體模型;每個方法在執行的同事都會建立一個棧幀用於儲存區域性變量表、運算元棧、動態連結、方法出口等資訊。每個方法從呼叫直至執行完成的過程,就對應著一個棧幀在虛擬機器棧中入棧到出棧的過程。
Java虛擬機器規範中,對這個區域規定了兩種異常狀態:如果執行緒請求的棧深度大於虛擬機器所允許的深度,將丟擲StackOverflowError異常;如果虛擬機器棧可以動態擴充套件,如果擴充套件時無法申請到足夠的記憶體,就會丟擲
3、本地方法棧
本地方法棧與虛擬機器棧所發揮的作用是相似的,他們之間的區別不過是虛擬機器棧為虛擬機器執行Java方法服務,而本地方法棧則為虛擬機器使用的Native方法服務。有的虛擬機器(Sun HotSpot)直接把本地方法棧和虛擬機器棧合二為一。會丟擲StackOverflowError和OutOfMemoryError。
4、Java堆
Java堆是Java虛擬機器所管理的記憶體中最大的一塊。所有執行緒共享這塊記憶體區域,在虛擬機器啟動時建立。此記憶體區域的唯一目的就是存放物件例項,幾乎所有的物件例項都是在這裡分配記憶體。
Java堆是垃圾收集器管理的主要區域,從記憶體回收的角度來看,由於現在收集器基本都採用分代收集演算法,所以
Java堆可以處於物理上不連續的記憶體空間中,只要邏輯上是連續的即可。
5、方法區
各個執行緒共享的記憶體區域,他用於儲存已被虛擬機器載入的類資訊、常量、靜態變數、即時編譯器編譯後的程式碼等資料。Java虛擬機器規範把方法區描述為堆的一個邏輯部分。HotSpot中,有人把方法區稱為“永久代”。
6、執行時常量池
執行時常量池是方法區的一部分。Class檔案中除了有類的版本、欄位、方法、介面等描述資訊外,還有一項資訊是常量池,用於存放編譯期生成的各種字面量和符號引用,這部分記憶體將在類載入後進入方法區的執行時常量池中存放。
執行時常量池相對於Class檔案常量池的另外一個重要特徵是具備動態性。
6、直接記憶體
直接記憶體並不是虛擬機器執行時資料區的一部分,也不是Java虛擬機器規範中定義的記憶體區域。
在JDK1.4中新加入了NIO類,引入了一種基於通道與緩衝區的I/O方式,他可以使用Native函式庫直接分配堆外記憶體,然後通過一個儲存在Java堆中的DirectByteBuffer物件作為這塊記憶體的引用進行操作。這樣避免了再Java堆和Native堆中來回複製資料。
HotSpot虛擬機器物件探祕
1、物件的建立
Java堆是否規整(是否規整由所採用的垃圾收集器是否帶有壓縮整理功能決定):
規整:指標碰撞
不規整:空閒列表
分配記憶體;初始化。
2、物件的記憶體佈局
在HotSpot虛擬機器中,物件在記憶體中儲存的佈局可以分為3塊區域:物件頭(Header)、例項資料(Instance Data)和對齊填充(Padding)。
物件頭包括兩部分資訊,第一部分用於儲存物件自身的執行時資料,如雜湊碼、GC分代年齡、鎖狀態標誌、執行緒持有的鎖、偏向執行緒ID、偏向時間戳等。資料長度在32位和64位虛擬機器(為開啟壓縮指標)中分別為32bit和64bit,官方稱他為“Mark Word”。另一部分是型別指標,即物件指向他的類元資料的指標,虛擬機器通過這個指標來確定這個物件是那個類的例項。如果物件是一個Java陣列,那在物件頭中還必須有一塊用於記錄陣列長度的資料。
例項資料是物件真正儲存的有效資訊,也是在程式程式碼中所定義的各種型別的欄位內容。無論是從父類繼承下來的,還是在子類中定義的,都需要記錄起來。
對齊填充並不是必然存在的,也沒有特別的含義,HotSpot VM是8位元組對齊。
3、物件的訪問定位
建立物件是為了使用物件,我們的Java程式需要通過棧上的reference資料來操作堆上的具體物件。目前主流的訪問方式有使用控制代碼和直接指標兩種。
控制代碼訪問,Java堆中將會劃分出一塊記憶體來作為控制代碼池,reference中儲存的就是物件的控制代碼地址,控制代碼中包含了物件例項資料與型別資料各自的具體地址資訊。
直接指標訪問,Java堆物件的佈局中就必須考慮如何放置訪問型別資料的相關資訊,而reference中儲存的直接就是物件地址。
比較:
控制代碼訪問最大好處就是reference中儲存的是穩定的控制代碼地址,物件被移動時只會改變控制代碼中的例項資料指標,reference本身不需要修改。
直接指標訪問方式的最大好處就是速度更快,他節省了一次指標定位的時間開銷。HotSpot就是採用的這種方式。
實戰:OutOfMemoryError異常
1、Java堆溢位
Java堆用於儲存物件例項,只要不斷地建立物件,並且保證GC Roots到物件之間有可達路徑來避免垃圾回收機制清除這些物件。
import java.util.ArrayList;
import java.util.List;
public class HeapOOM {
public static void main(String args[]) {
List<OOMObject> list = new ArrayList<OOMObject>();
while(true) {
list.add(new OOMObject());
}
}
}
2、虛擬機器棧和本地方法棧溢位
public class VMStackOF {
private int length = 1;
public void stackLeak() {
length++;
stackLeak();
}
public static void main(String args[]) {
VMStackOF vmStackOF = new VMStackOF();
vmStackOF.stackLeak();
}
}
3、方法區和執行時常量池溢位
4、本機直接記憶體溢位
相關推薦
《深入理解Java虛擬機器—JVM高階特性與實踐 周志明 著》之第2章 Java記憶體區域與記憶體溢位異常
1、Java虛擬機器所管理的記憶體包括以下幾個執行時資料區域: 2、程式計數器: 1. 可以看作是當前執行緒所執行的位元組碼的行號指示器,是一塊較小的記憶體空間; &nbs
JVM 第2章 Java記憶體區域與記憶體溢位異常
可以參考下,這個寫的簡練 https://blog.csdn.net/seu_calvin/article/details/51404589 1 概述 對於java程式設計師來說,在虛擬機器自動記憶體管理機制的幫助下,不需要為每一個new操作去寫配對的delete/free程式碼,不
第2章 Java記憶體區域與記憶體溢位異常
2.2 執行時資料區 方法區、堆、執行引擎、本地庫介面 虛擬機器棧、本地方法棧、程式計數器 加粗是所有執行緒共享的資料區,其他是執行緒隔離的資料區 2.2.1 程式計數器 是較小的記憶體空間,是當前執行緒執行的位元組碼的行號指示器。位元組碼指示器就
第2章-Java記憶體區域與記憶體溢位異常
Java記憶體區域與記憶體溢位異常 概述 對於Java程式設計師來說,在虛擬機器自動記憶體管理機制的幫助下,不再需要為每一個new操作去寫配對的delete/free程式碼,不容易出現記憶體洩漏和記憶體溢位問題,由虛擬機器管理記憶體。 執行時資料區域 Java虛擬機器在執行
筆記:深入理解JVM 第2章 Java記憶體區域與記憶體溢位
1、JVM 執行時資料區 所有執行緒共享的資料區:方法區(持久代)、堆區 執行緒隔離的資料區:程式計數器、Java虛擬機器棧區 堆區構成:新生代 ( 由Eden, From Survivor, To Survivor 構成)、老生代 執行時常量池:方法區一部分,用於存放編
深入理解Java虛擬機器----第2章 Java記憶體區域與記憶體溢位異常
第2章 Java記憶體區域與記憶體溢位異常 2.3 HotSpot 虛擬機器物件探祕 2.3.1 物件的建立 Java作為一門面向物件語言,在程式執行過程中會產生大量的物件,在語言層面上來看,建立一個物件僅僅需要一個new關鍵字即可,但是在虛
第2章 Java記憶體區域與記憶體溢位異常
執行時資料區域 程式計數器 程式計數器是一塊較小的記憶體空間,他可以看作是當前執行緒所執行的位元組碼的行號指示器。在虛擬機器的概念模型裡(僅是概念模型,各種虛擬機器可能會通過 一些更搞笑的方式去實現),位元組碼直譯器工作時就是通過改變這個計數器的值來選取下一條需要
JAVA虛擬機器(JVM)劃重點 第二章 Java記憶體區域與記憶體溢位異常 之 虛擬機器物件
本部落格參考《深入理解Java虛擬機器》(第二版)一書,提取重點知識,再加以個人的理解編寫而成。轉載請標明來源。 JAVA虛擬機器(JVM)劃重點 第二章 Java記憶體區域與記憶體溢位異常 之 虛擬機器物件 Java物件的建立 1、類載入過程
JAVA虛擬機器(JVM)劃重點 第二章 Java記憶體區域與記憶體溢位異常 之 執行時資料區域
本部落格參考《深入理解Java虛擬機器》(第二版)一書,提取重點知識,再加以個人的理解編寫而成。轉載請標明來源。 JVM劃重點 第二章 Java記憶體區域與記憶體溢位異常 之 執行時資料區域 概述 執行時資料區域 程式計數器 Java虛擬機
第二章、Java記憶體區域與記憶體溢位異常
2.1 概述 對於Java程式設計師來說,虛擬機器具有自動記憶體管理機制,不容易出現記憶體洩漏和記憶體溢位問題。也正是因為Java程式設計師把記憶體控制的機制交給了Java虛擬機器,一旦出現記憶體洩漏和溢位方面的問題,如果不瞭解虛擬機器是怎樣使用記憶體的,那排查
深入理解JVM—第二章:Java記憶體區域與記憶體溢位異常
1,概述 Java較C、C++,Java可以利用虛擬機器的自動記憶體管理機制,避免繁瑣的記憶體分配與回收。不容易出現記憶體洩漏和記憶體溢位問題。 記憶體洩漏:指程式申請到的記憶體空間不再歸還(無法歸還),可使用完該記憶體空間的程式也不能再訪問該空間(
第二章Java記憶體區域與記憶體溢位異常
JVM記憶體模型及特徵: 堆: 1.JVM管理記憶體中最大的一塊,被所有執行緒共享 2.唯一目的是存放物件例項和陣列 3.垃圾蒐集器管理的主要區域 4.可擴充套件,通過-Xmx和-Xms來控制 5.如果在堆中沒有記憶體完成例項分配,並且堆也無法再擴充套件時,將會丟擲OutO
深入理解java虛擬機器-第二章:java記憶體區域與記憶體洩露異常
2.1概述: java將記憶體的管理(主要是回收工作),交由jvm管理,確實很省事,但是一點jvm因記憶體出現問題,排查起來將會很困難,為了能夠成為獨當一面的大牛呢,自然要了解vm是怎麼去使用記憶體的。 2.2執行時的資料區域 vm會將管理的記憶體劃分為不同的區域,不同的區域間有各自的用途,以及建立和
第二章 java記憶體區域與記憶體溢位異常
一、執行時的資料區域 java虛擬機器執行時的資料區域 主要分為以下幾個區域: 1 、程式計數器 它佔用較小的一塊記憶體空間,可以看做是當前執行緒執行的位元組碼的行號指示器。每個執行緒都需要擁有自己的的程式計數器,以滿足在多執行緒情況下,執行緒不斷切換自身能夠
《深入理解Java虛擬機器》讀書筆記:第二章Java記憶體區域與記憶體溢位異常
Java虛擬機器在執行Java程式的過程中會把它所管理的記憶體劃分為若干個不同的資料區域:方法區、虛擬機器棧、本地方法棧、堆、程式計數器 程式計數器(ProgramCounterRegister):一塊較小的記憶體空間,看作當前執行緒所執行的位元組碼的行號指示器;位元組碼
學習筆記1:深入理解Java虛擬機器——JVM高階特性與最佳實踐_走進java_java記憶體區域與記憶體溢位異常
第一部分:走進java Java虛擬機器 程式碼在華章下載 jdk釋出了六個命令列工具和兩個視覺化故障處理工具。 推薦書籍 設計原本 領域特定語言 現在著名的Java虛擬機器 hotspot vm(預設) jrockit vm j9 vm jdk sun jdk op
java虛擬機器—-java記憶體區域與記憶體溢位異常
一,java虛擬機器所管理的執行時資料區域分為:程式計數器、java虛擬機器棧、本地方法棧、java堆、方法區、執行時常量池。 1,程式計數器:
jvm_第三章:垃圾收集與記憶體分配策略
1:回收哪些記憶體: 程式計數器,虛擬機器棧,本地方法棧屬於執行緒私有,隨執行緒而生,隨執行緒而滅,所以主要考慮方法區和堆記憶體的回收:2 2:哪些物件可以被回收: 引用計數演算法: 可達性分析演算法:GCRoots包括: 虛擬機器棧中的引用的物件;
《深入理解java虛擬機器》讀書筆記(二)---- Java記憶體區域與記憶體溢位異常
執行時資料區域 java虛擬機器所管理的記憶體將會包括以下幾個執行時資料區域: 1、程式計數器 程式計數器是一塊較小的記憶體空間,它可以看作是當前執行緒所執行位元組碼的行號指示器。在虛擬機器的概念模型裡,位元組碼直譯器的工作就是通過改變這個計數器的值來選取下一條需要執
JVM-Java記憶體區域與記憶體溢位
JVM虛擬機器執行時資料區結構分為: 其中方法區和堆是所有執行緒共享的記憶體區域,而Java棧、本地方法棧、程式計數器是執行緒私有的。 我們詳細介紹執行時資料區的各個區域及其作用。 程式計數器: 一塊較小的記憶體空間,位元組碼指示器工作時通過改變計數器的值來選取下一條需