JAVA JVM運行時數據區(qū)詳解
一、前言
這是JVM系列文章的第三篇,這篇文章將對整個JVM運行時數據區(qū)和GC垃圾回收詳細的介紹。這部分也算是JVM的核心內容了。
二、運行時數據區(qū)整體概架構
以下是自己的一句話總結:
分為線程私有和線程共享的兩大類,其中程序計數器、虛擬機棧、本地方法棧是屬于線程私有的,堆內存及方法區(qū)內存是線程共享的。程序計數器主要是記錄字節(jié)碼指令,CPU上下文切換線程,從一個線程切換到另一個線程,需要知道線程執(zhí)行到哪一步,所以記錄這個指令就是很有必要的,程序計數器無OOM和GC的發(fā)生。虛擬機棧里面是一個個棧幀,每一個棧幀對應著每一個方法,棧幀又是由局部變量表、操作數棧、方法返回值地址、動態(tài)鏈接組成。虛擬機??赡軙l(fā)生棧溢出異常,即starkoverflow本地方法棧是存放本地方法相關的東西;堆是一塊很大的空間,整體分為2大塊,新生代和老年代,新生代又分了Eden區(qū)、S0區(qū)、S1區(qū),垃圾回收主要發(fā)生在新生代,每一個區(qū)對應不同的垃圾回收算法;方法區(qū)保存的是一些常量、類的基本信息等,方法區(qū)對應的實現(xiàn)在JDK7中是永久代,在JDK8中是元空間。
三、程序計數器
用來儲存指向下一條指令的地址,是線程私有的,生命周期和線程的生命周期一致。
四、虛擬機棧
虛擬機棧是線程私有的,內部保存一個個棧幀,每一個棧幀對應一個Java方法的調用,生命周期和線程的生命周期保持一致。先來看看棧的特點。
1、棧的特點
棧是運行時的單位,而堆是存儲的單位。棧的特點是先進后出,后進先出。
可以通過參數-Xss來設置??臻g大小
2、棧幀的內部結構
3、局部變量表
是一個數字數組,主要用于存儲方法參數和定義在方法內的局部變量,這些數據類型包括各類基本數據類型,對象引用等,所需的容量大小是在編譯期確定下來的,在方法運行期間是不會改變局部變量表大小的。
關于Slot的理解:
靜態(tài)變量和局部變量的區(qū)別:
總結:
在棧幀中,與性能關系最為密切的就是局部變量表,在方法執(zhí)行時,虛擬機使用局部變量表完成完成方法的傳遞,局部變量表中的數據也是可達性分析中的GC Root,如果一個對象在局部變量表中還有引用,那么根絕可達性分析算法,這個變量就不屬于垃圾對象,是不會被GC回收的。
4、操作數棧
操作數棧是棧中棧,也可稱為表達式棧,在方法執(zhí)行過程中,根據字節(jié)碼指令,往棧中寫入數據或提取數據,即入棧和出棧。主要用于保存計算過程的中間結果。操作數棧,可以看成是臨時寄存器,計算過程中變量的臨時保存
5、動態(tài)鏈接
方法重寫的本質
6、方法返回地址
存放調用該方法的PC寄存器的值
五、本地方法棧
管理本地native本地方法,是線程私有的,所謂的本地方法,其實就是一些非Java語言寫的代碼,這部分代碼甚至可以和操作系統(tǒng)CPU進行打交道。
六、堆
堆是內存管理的核心區(qū)域,是線程共享的,屬于JVM級別,也就是一個JVM實例就會有一個堆空間,注意的是雖然堆整體上是線程共享的,但是在內部有一小塊空間是線程私有的緩存區(qū)TLAB。
幾乎所有的對象實例都是在堆中,堆是GC垃圾回收的重點區(qū)域。堆整體可以分為新生代和老年代,新生代又分為Eden區(qū)和S0和S1區(qū)。
新生代和老年代的比例是1:2,Eden區(qū)和s0,s1區(qū)所占空間比例是8:1:1
1、設置堆大小的參數
-Xms
:用于表示堆區(qū)的起始內存,默認情況下,占物理內存大小的64分之一。
-Xmx
用于表示堆區(qū)的最大內存,默認情況下,占物理內存的四分之一。
通常起始內存和最大內存兩個參數設置成一樣,目的是為了GC清理完堆區(qū)內存后不需要重新分隔 計算堆區(qū)的大小,從而提高性能。 查看設置的參數: 方式一:jps(查看進程) jstat -gc 進程id 方式二:-xx:+printGCDetails
2、對象分配過程
這里s0和s1誰是空的誰就是to,年齡計數器閾值是15,YGC是在Eden區(qū)滿的時候會觸發(fā),s0和s1滿的時候不會觸發(fā)YGC,YGC會將s區(qū)以及伊甸園區(qū)一起GC
關于垃圾回收,頻繁在新生區(qū)收集,很少在養(yǎng)老區(qū)收集,幾乎不在永久區(qū)/元空間收集。
Visualvm是JVM常用調優(yōu)工具,在JDK的bin下就可以打開
3、堆中的GC
年輕代(Minor GC)觸發(fā)機制
老年代GC(Major GC/Full GC)觸發(fā)機制
Full GC 觸發(fā)機制
4、內存分配策略
5、什么是TLAB
TLAB表明堆不一定是共享的。
6、堆是分配對象存儲的唯一選擇嗎?
如果經過逃逸分析,一個對象并沒有逃逸出方法的話,那么就有可能被優(yōu)化成棧上分配。
逃逸分析手段:
注意:JDK6U23版本后,HotSpot默認已經開啟逃逸分析。所以我們得出一個結論,開發(fā)中能使用局部變量的,就不要使用在方法外定義。JDK7后字符串常量池和靜態(tài)變量存儲在堆中
七、方法區(qū)
方法區(qū)可以看做是一塊獨立于堆的內存空間,是線程共享的,主要存儲類信息、運行時常量池等,也會發(fā)生OOM,JDK8前成為永久代,JDK8成為元空間。(元空間和永久代最大的區(qū)別是,元空間不再使用JVM內存,而是使用了本地內存技術)
1、方法區(qū)概述
2、設置方法區(qū)內存大小
3、如何解決OOM問題?
4、方法區(qū)存儲什么
5、方法區(qū)的演進細節(jié)
6、方法區(qū)的GC
總結
本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關注腳本之家的更多內容!
相關文章
Java使用OpenCV3.2實現(xiàn)視頻讀取與播放
這篇文章主要為大家詳細介紹了Java使用OpenCV3.2實現(xiàn)視頻讀取與播放,具有一定的參考價值,感興趣的小伙伴們可以參考一下2019-07-07JAVA中通過Redis實現(xiàn)延時任務demo實例
Redis在2.0版本時引入了發(fā)布訂閱(pub/sub)功能,在發(fā)布訂閱中有一個channel(頻道),與消息隊列中的topic(主題)類似,可以通過redis的發(fā)布訂閱者模式實現(xiàn)延時任務功能,實例中會議室預約系統(tǒng),用戶預約管理員審核后生效,如未審批,需要自動變超期未處理,使用延時任務2024-08-08Mybatis注解開發(fā)單表、多表操作的實現(xiàn)代碼
這篇文章主要介紹了Mybatis高級:Mybatis注解開發(fā)單表操作,Mybatis注解開發(fā)多表操作,構建sql語句,綜合案例學生管理系統(tǒng)使用接口注解方式優(yōu)化,需要的朋友可以參考下2021-02-02SpringMVC中的HandlerMapping和HandlerAdapter詳解
這篇文章主要介紹了SpringMVC中的HandlerMapping和HandlerAdapter詳解,在Spring MVC中,HandlerMapping(處理器映射器)用于確定請求處理器對象,請求處理器可以是任何對象,只要它們使用了@Controller注解或注解@RequestMapping,需要的朋友可以參考下2023-08-08仿京東平臺框架開發(fā)開放平臺(包含需求,服務端代碼,SDK代碼)
現(xiàn)在開放平臺越來越多了,下面針對仿京東開放平臺框架,封裝自己的開放平臺,分享給大家。先感謝一下京東開放平臺的技術大佬們,下面從開放平臺需求,服務端代碼,SDK代碼三大塊進行分享2021-06-06SpringBoot自定義注解使用讀寫分離Mysql數據庫的實例教程
這篇文章主要給大家介紹了關于SpringBoot自定義注解使用讀寫分離Mysql數據庫的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-11-11JAVA Iterator接口與增強for循環(huán)的實現(xiàn)
這篇文章主要介紹了JAVA Iterator接口與增強for循環(huán)的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-11-11