第一章 JVM記憶體結構
注意:本系列部落格,主要參考自以下四本書
《分散式Java應用:基礎與實踐》《深入理解Java虛擬機器(第二版)》《深入分析Java web技術內幕》《實戰java虛擬機器》
1、為什麼要了解JVM記憶體管理機制
- JVM自動的管理記憶體的分配與回收,這會在不知不覺中浪費很多記憶體,導致JVM花費很多時間去進行垃圾回收(GC)
- 記憶體洩露,導致JVM記憶體最終不夠用
2、JVM記憶體結構
根據上圖,JVM記憶體結構包括:
- 方法區(也就是"持久代"),java8裡徹底被移除,取而代之的是元資料區
- 堆
- 棧(在hotspot JVM中,JVM方法棧--Java虛擬棧,與本地方法棧是同一個)
- PC暫存器(程式計數器)
還有一塊:
- 直接記憶體:直接向系統記憶體申請的一塊記憶體區域,javaNIO會使用,速度優於java堆記憶體。- 隸屬於實體記憶體,不屬於JVM記憶體
注意點:
- 堆是GC的主要區域,方法區、直接記憶體也會發生GC
- 棧與PC暫存器是每個執行緒都會建立的私有區域,不會GC
- 直接記憶體使用速度由於堆記憶體,但是記憶體的申請速度低於堆記憶體
2.1、方法區
- 存放內容(類的資訊、類static屬性、方法、常量池)
- 已經載入的類的資訊(名稱、修飾符等)
- 類中的static變數
- 類中的field資訊
- 類中定義為final常量
- 類中的方法資訊
- 執行時常量池:編譯器生成的各種字面量和符號引用(編譯期)儲存在class檔案的常量池中,這部分內容會在類載入之後進入執行時常量池,class檔案的常量池檢視 第三章 類檔案結構與javap的使用
- 使用例項:反射,在程式中通過Class物件呼叫getName等方法獲取資訊資料時,這些資訊資料來源於方法區。
- 調節引數
- -XX:PermSize:指定方法區的最小值,預設為16M
- -XX:MaxPermSize:指定方法區的最大值,預設為64M
- 所拋錯誤
- 方法區域要使用的記憶體超過了其允許的大小時,丟擲OutOfMemoryError
- 記憶體回收的主要目標
- 對類的解除安裝(這也是為什麼很多企業使用velocity等模板引擎做前端而不是使用jsp的原因之一)
- 針對常量池的回收
- 對類的解除安裝(這也是為什麼很多企業使用velocity等模板引擎做前端而不是使用jsp的原因之一)
- 總結
- 一般而言,在企業開發中,-XX:PermSize==-XX:MaxPermSize
- 通常,這個大小設定為256M就沒問題了,當然還要根據自己的程式去預估,並在執行過程中去調整,這裡以在Resin伺服器中配置為例
<jvm-arg>-XX:PermSize=256M</jvm-arg> <jvm-arg>-XX:MaxPermSize=256M</jvm-arg>
View Code - 類中的static變數會在方法區分配記憶體,但是類中的例項變數不會(類中的例項變數會隨著物件例項的建立一起分配在堆中,當然若是基本資料型別的話,會隨著物件的建立直接壓入運算元棧)
- 關於方法區的存放內容,可以這樣去想所有的通過Class物件可以反射獲取的都是從方法區獲取的(包括Class物件也是方法區的,Class是該類下所有其他資訊的訪問入口)
注意:常量池在jdk1.6在方法區;在jdk1.7在堆
附:元資料區
- 調節引數:-XX:MaxMetaspaceSize,如果不指定大小,極限情況下可能耗盡系統所有記憶體
- 元資料區是堆外的一塊直接記憶體
2.2、堆
- 存放內容
- 物件例項(類中的例項變數會隨著物件例項的建立一起分配在堆中,當然若是基本資料型別的話,會隨著物件的建立直接壓入運算元棧),這一點檢視 第四章 類載入機制
- 陣列值
- 使用例項
- 所有通過new建立的物件都在這塊兒記憶體分配,具體分配到年輕代還是年老代需要根據配置引數而定(新建物件直接分配到年老代有兩種情況,看下邊)
- 調節引數
- -Xmx:最大堆記憶體,預設為實體記憶體的1/4但小於1G
- -Xms:最小堆記憶體,預設為實體記憶體的1/64但小於1G
- -XX:MinHeapFreeRatio,預設當空餘堆記憶體小於最小堆記憶體的40%時,堆記憶體增大到-Xmx
- -XX:MaxHeapFreeRatio,當空餘堆記憶體大於最大堆記憶體的70%時,堆記憶體減小到-Xms
- 注意點
- 在實際使用中,-Xmx與-Xms配置成相等的,這樣,堆記憶體就不會頻繁的進行調整了
- 丟擲錯誤
- OutOfMemoryError:在堆中沒有記憶體完成例項分配(關於例項記憶體的分配,之後再說),此時堆記憶體已達到最大無法擴充套件時。
- 堆記憶體劃分
-
- 新生代
- 組成:Eden+From(S0)+To(S1)
- -Xmn:整個新生代的大小
- -XX:SurvivorRatio:調整Eden:From(To)的比率,預設為8:1
- 年老代
- 新建物件直接分配到年老代,兩種情況
- 大物件:-XX:PretenureSizeThreshold(單位:位元組)引數來指定大物件的標準,在Parallel Scavenge GC下可能無效,
- 大陣列:陣列中的元素沒有引用任何外部的物件
- 新建物件直接分配到年老代,兩種情況
- 新生代
- 總結
- 企業開發中,-Xmx==-Xms
- 通常,-Xmx設定為2048m就沒問題了,當然還要根據自己的程式去預估,並在執行過程中去調整,這裡以在Resin伺服器中配置為例
<jvm-arg>-Xms2048m</jvm-arg> <jvm-arg>-Xmx2048m</jvm-arg> <jvm-arg>-Xmn512m</jvm-arg> <jvm-arg>-XX:SurvivorRatio=8</jvm-arg> <jvm-arg>-XX:MaxTenuringThreshold=15</jvm-arg>
View Code可以看到,-Xms==-Xmx==2048m,年輕代大小-Xmn==512m,這樣,年老代大小就是2048-512==1536m,這個比率值得記住,在企業開發中,年輕代:年老代==1:3,而此時,我們配置的-XX:MaxTenuringThreshold=15(這也是預設值),年輕代物件經過15次的複製後進入到年老代(關於這一點,在之後的GC機制中會說),
- -XX:MaxTenuringThreshold與-XX:PretenureSizeThreshold不一樣,不要看錯
2.3、棧
- 注意點
- 每條執行緒都會分配一個棧,每個棧中有多個棧幀(每一個方法對應一個棧幀)
- 執行緒建立的時候建立一個執行緒的java棧
- 每個方法在執行的同時都會建立一個棧幀,每個棧幀用於儲存當前方法的區域性變量表、運算元棧等,具體檢視本文第一個圖,每一個方法從呼叫直至執行完成的過程,就對應著一個棧幀在虛擬機器棧中入棧到出棧的過程,說的更明白一點,就是方法執行時建立棧幀,方法結束時釋放棧幀所佔記憶體
- 存放內容
- 區域性變量表:八大基本資料型別資料、物件引用。該空間在編譯期已經分配好,執行期不變。
- 運算元棧:是執行引擎直接操作的部分
- 調節引數
- -Xss:設定棧的大小,通常設定為1m就好
<jvm-arg>-Xss1m</jvm-arg>
View Code
- -Xss:設定棧的大小,通常設定為1m就好
- 支援native方法執行(本地方法棧)
- 所拋錯誤
- StackOverFlowError:執行緒請求的棧深度大於虛擬機器所允許的深度。
- 棧的深度就是方法呼叫巢狀的層數,受限於-Xss的大小
- 典型場景:沒有終止條件的遞迴(遞迴基於棧)。
- 每個方法的棧的深度在javac編譯之後就已經確定了,檢視 第三章 類檔案結構與javap的使用
- OutOfMemoryError:虛擬機器棧可以動態擴充套件,如果擴充套件的時候無法申請到足夠的記憶體。
- 需要注意的是,棧可以動態擴充套件,但是棧中的區域性變量表不可以。
- StackOverFlowError:執行緒請求的棧深度大於虛擬機器所允許的深度。
2.4、PC暫存器(程式計數器)
- 概念:當前執行緒所執行的位元組碼的行號指示器,用於位元組碼直譯器對位元組碼指令的執行。
- 多執行緒:通過執行緒輪流切換並分配處理器執行時間的方式來實現的,在任何一個時刻,一個處理器(也就是一個核)只能執行一條執行緒中的指令,為了執行緒切換後能恢復到正確的執行位置,每條執行緒都要有一個獨立的程式計數器,各條執行緒之間計數器互不影響,獨立儲存。
附:物件分配(《實戰java虛擬機器》)
相關推薦
第一章 JVM記憶體結構
注意:本系列部落格,主要參考自以下四本書 《分散式Java應用:基礎與實踐》《深入理解Java虛擬機器(第二版)》《深入分析Java web技術內幕》《實戰java虛擬機器》 1、為什麼要了解JVM記憶體管理機制 JVM自動的管理記憶體的分配與回收,這會在不知不覺中浪費很多記憶體,導致JVM花費很多
第七章 JVM體系結構與工作方式
硬件 java內存管理 彈出 操作符 clas 基本 記錄器 pan 操作 JVM能跨計算機體系結構來執行Java字節碼,主要是由於JVM屏蔽了與各個計算機平臺的軟件和硬件之間的差異。 7.1 JVM體系結構 7.1.1 何謂JVM 模擬一個計算機來達到一個計算
JVM記憶體結構、Java記憶體模型以及Java物件模型之間的區別
Java作為一種面向物件的,跨平臺語言,其物件、記憶體等一直是比較難的知識點。而且很多概念的名稱看起來又那麼相似,很多人會傻傻分不清楚。比如本文我們要討論的JVM記憶體結構、Java記憶體模型和Java物件模型,這就是三個截然不同的概念,但是很多人容易弄混。 可以這樣說,很多高階開發甚至都搞
jvm 記憶體結構初步理解
執行緒隔離區 1. 虛擬機器棧:當方法執行時 會建立虛擬棧幀 儲存區域性變量表運算元棧,動態連結和方法出口,而初學者說的’堆疊’指的是棧中棧幀的區域性變量表中的內容,會存放編譯期可知的所有的基本資料型別,和物件型別的引用; 2. 本地方法棧:作用與虛擬機器棧類似,但是是讀取本地方法的; 3.
JVM(一)JVM記憶體結構
Java程式碼需要執行在虛擬機器(JVM)上,而JVM為了方便管理記憶體,會把自己所管理的記憶體劃分為若干個不同的資料區域,用作不同的用途,先看一下大致劃分 堆 存放內容: ·大多數建立的物件 ·陣列值 GC情況:
JVM記憶體結構?為什麼需要GC?
原 https://blog.csdn.net/tonytfjing/article/details/44278233 JVM結構、記憶體分配、垃圾回收演算法、垃圾收集器 1.方法區(Method Area) 2.堆區(Heap) 3.虛擬機器棧(VM Stack) 4.本地方法棧(
知識點整理1:JVM記憶體結構
JVM把記憶體分為如下幾個區域: 1.方法區(Method Area) 2.堆區(Heap) 3.虛擬機器棧(VM Stack) 4.本地方法棧(Native Method Stack) 5.程式計數器(Program Counter R
JVM記憶體結構佈局
Java的記憶體結構 JVM記憶體結構主要有三大塊:堆記憶體、方法區和棧。 堆記憶體是JVM中最大的一塊由年輕代和老年代組成,而年輕代記憶體又被分成三部分,Eden空間、From Survivor空間、To Survivor空間,預設情況下年輕代按照8:1:1的比例
深入淺出JVM(jvm記憶體結構,類載入器圖,雙親委託模式,堆記憶體,GC解析,GC演算法)
目錄 Java虛擬機器的記憶體結構: 類載入器圖: 雙親委託模式: 堆記憶體: GC解析圖: GC演算法 Java虛擬機器的記憶體結構: 類載入器圖: 雙親委託模式: Java允許建立和JDK自帶類
一、基礎篇(JVM記憶體結構)
一.概念 JAVA的JVM的記憶體可分為3個區:堆(heap)、棧(stack)和方法區(method) 1)堆區: a.儲存的全部是物件,每個物件都包含一個與之對應的class的資訊。(class的目的是得到操作指令) b.jvm只有一個堆區(heap)被所有執行緒共享,堆中不存放
JVM-JVM記憶體結構
一、概念 Java虛擬機器——JVM,,JVM我們可以想象為一個DOS程式,java之所以能做到“一次編譯,處處執行”,就是因為它的存在。java程式從原始碼到執行三個階段:編碼--編譯--執行,其中jvm在其中的角色就是編譯階段,將.class檔案解釋為機器碼,也就是說,只要有了jvm,那麼不管
深入理解JAVA虛擬機器2:JVM記憶體結構
記憶體結構一覽 在上一篇文章中,我們最後給出了一幅圖 這幅圖中,就包含了JVM的記憶體結構的所有組成元素,他們分別是:java堆記憶體、java棧、方法區、本地方法區以及pc暫存器,接下來我們就對這些區域逐一介紹。 java堆 Java堆是Java虛擬
JVM記憶體結構詳解
主要內容如下: JVM啟動流程 JVM基本結構 記憶體模型 編譯和解釋執行的概念 一、JVM啟動流程: JVM啟動時,是由java命令/javaw命令來啟動的。 二、JVM基本結構: JVM基本結構圖: 《深入理解Ja
Jvm--01、Jvm記憶體結構
HotSpot VM,它是Sun JDK和OpenJDK中所帶的虛擬機器,也是目前使用範圍最廣的Java虛擬機器。 話不多說上圖、Jvm記憶體結構圖: 深入理解Java虛擬機器(第二版)如圖: 方法區和堆是執行緒共享的、所有會有執行緒安
JVM記憶體結構 VS Java記憶體模型 VS Java物件模型
Java作為一種面向物件的,跨平臺語言,其物件、記憶體等一直是比較難的知識點。而且很多概念的名稱看起來又那麼相似,很多人會傻傻分不清楚。比如本文我們要討論的JVM記憶體結構、Java記憶體模型和Java物件模型,這就是三個截然不同的概念,但是很多人容易弄混。 可以這樣說
Mybatis的原理與JVM記憶體結構(面試題)
Mybatis的原理 1.Mapper 介面在初始SQL SessionFactory註冊的 2.Mapper 介面註冊在名為MapperRegistry類的 HasMap中 key=Mapper class value = 建立當前Mapper的工廠 3.
JVM記憶體結構(Java 工程師成神之路·基礎篇·JVM)
第一章 JVM記憶體結構 第一章 JVM記憶體結構 為什麼要了解JVM記憶體管理機制 JVM自動的管理記憶體的分配與回收,這會在不知不覺中浪費很多記憶體,導致JVM花費很多時間去進行垃圾回收(GC) 記憶體洩露,導致JVM記憶體最終不夠用 JVM記憶體結構
JVM記憶體結構------堆,棧,方法區,以及堆和棧的區別
一 、 定義 堆:FIFO佇列優先,先進先出。JVM只有一個堆區被所有執行緒所共享!堆存放在耳機快取中,呼叫物件的速度相對慢一些,生命週期由JVM的垃圾回收機制定。 棧:FILO先進後出,暫存資料的地方。每個執行緒都包含一個棧區!棧存放在一級快取中,存取速度較快,“棧是限定
JVM記憶體結構--新生代及新生代裡的兩個Survivor區(下一輪S0與S1交換角色,如此迴圈往復)、常見調優引數
轉自http://www.cnblogs.com/duanxz/p/6076662.html 一、為什麼會有年輕代 我們先來屢屢,為什麼需要把堆分代?不分代不能完成他所做的事情麼?其實不分代完全可以,分代的唯一理由就是優化GC效能。你先想想,如果沒有分代,那我們
Java虛擬機器詳解----JVM記憶體結構
http://www.cnblogs.com/smyhvae/p/4748392.htm 主要內容如下: JVM啟動流程 JVM基本結構 記憶體模型 編譯和解釋執行的概念 一、JVM啟動流程: JVM啟動時,是由java命令/javaw命令來啟