java 句柄 内存_Java内存区域学习
運(yùn)行時區(qū)域
Java虛擬機(jī)在執(zhí)行Java程序過程中把其所管理的內(nèi)存劃分成若干個不同的數(shù)據(jù)區(qū)域。
程序計數(shù)器
當(dāng)前線程所執(zhí)行的字節(jié)碼的指示器。通過改變這個計數(shù)器的值來選取下一個需要執(zhí)行的字節(jié)碼指令,分支、循環(huán)、跳轉(zhuǎn)、異常、線程恢復(fù)等都需要這個計數(shù)器完成。
每個線程一個獨(dú)立的程序計數(shù)器,各線程之間互不影響,獨(dú)立存儲。
執(zhí)行Java方法時:正在執(zhí)行虛擬字節(jié)碼的指令地址
執(zhí)行Native方法:值為空(Undefined)
復(fù)制代碼
唯一一個Java虛擬機(jī)規(guī)范中沒有規(guī)定OutOfMemoryError的區(qū)域
虛擬機(jī)棧
線程私有,生命周期和線程一致。
描述的是Java方法執(zhí)行的內(nèi)存模型:方法執(zhí)行同時創(chuàng)建一個棧幀,方法從調(diào)用到執(zhí)行完成,就是一個棧幀在虛擬機(jī)棧中入棧到出棧的過程。
其中棧幀用于存儲:局部變量表、操作數(shù)棧、動態(tài)鏈接、方法出口等信息。
局部變量表中存放了編譯期間可知的基本數(shù)據(jù)類型和對象引用。
64位的long和double類型的數(shù)據(jù)會占2個局部空間變量,其余類型只占1個。因局部變量表中所需內(nèi)存是在編譯期間完成的,所以這個方法在幀中需要分配多少局部變量空間是確定的。
這部分區(qū)域異常:StackOverFlowError和OutOfMemoryError
、
本地方法棧
與虛擬機(jī)棧的作用類似。本地方法棧是為Native方法服務(wù)。拋出異常與虛擬機(jī)棧一致。
堆
堆是Java虛擬機(jī)中內(nèi)存最大的一塊。線程共享,虛擬機(jī)啟動時創(chuàng)建。存放對象實(shí)例。
幾乎所有的對象都在這里分配內(nèi)存。【隨著JIT編譯器的發(fā)展和逃逸分析技術(shù)的成熟,棧上分配和標(biāo)量替換,對象不一定在堆中分配】
堆是垃圾收集管理器的主要區(qū)域,也叫GC堆。細(xì)分為:新生代、老年代。eden->from survivor->to survivor
通過-Xmx和-Xms控制擴(kuò)展,無法擴(kuò)展時拋出OutOfMemoryError異常
方法區(qū)
線程共享。存儲已被虛擬機(jī)加載的類信息、常量、靜態(tài)變量、即時編譯器編譯的代碼。也叫非堆,也稱永久代。
-XX:MaxPermSize
內(nèi)存回收目標(biāo):常量池的回收和類的卸載
OutOfMemoryError
運(yùn)行時常量池
方法區(qū)的一部分
OutOfMemoryError
直接內(nèi)存
不是虛擬機(jī)運(yùn)行時區(qū)的一部分。
JDK1.4新加入的NIO類,引入Channel和Buffer的I/O方式,使用Native函數(shù)庫直接分配堆外內(nèi)存,使用DirectByteBuffer作為這塊內(nèi)存的引用進(jìn)行操作。
受本機(jī)內(nèi)存大小和處理器尋址空間的限制
OutOfMemoryError
虛擬機(jī)中的對象
對象的創(chuàng)建
當(dāng)遇到new指令時
首先檢查這個指令的參數(shù)是否能在常量池中定位到一個類的符號引用。【并檢查該符號引用代表的類是否已被加載、解析、初始化過,若沒有則執(zhí)行類加載】
類加載通過之后,為新生對象分配內(nèi)存
內(nèi)存分配完成后,需將分配到的內(nèi)存空間都初始化為零值,不包括對象頭
接下來,虛擬機(jī)要對對象進(jìn)行必要的設(shè)置,設(shè)置對象頭。如這個對象是那個類的實(shí)例。如何才能找到類的元數(shù)據(jù)信息、對象的哈希碼、對象的GC分代年齡等信息。
復(fù)制代碼
分配內(nèi)存方式:
指針碰撞
空閑列表
復(fù)制代碼
當(dāng)使用Serial、ParNew等帶compact過程的收集器時:分配算法是指針碰撞
使用CMS基于Mark-Sweep算法的收集器時:分配算法采用空閑列表
分配對象內(nèi)存空間并發(fā)下線程安全問題:
采用CAS加上失敗重試保證更新的原子性
把內(nèi)存分配動作按線程劃分在不同的空間進(jìn)行,即每個線程在Java堆中預(yù)先分配一塊小內(nèi)存,成為本地線程分配緩沖區(qū)【TLAB】 -XX:+、-UseTLAB
復(fù)制代碼
對象創(chuàng)建完成之后還有進(jìn)行init,按照程序員的意愿進(jìn)行初始化。
對象內(nèi)存布局
對象內(nèi)存布局分為三塊
對象頭、實(shí)例數(shù)據(jù)、對齊填充
復(fù)制代碼
對象頭
對象頭包含兩部分:
存儲對象自身的運(yùn)行數(shù)據(jù)
類型指針
復(fù)制代碼
對象自身的運(yùn)行數(shù)據(jù)
包含哈希碼、GC分代年齡、鎖狀態(tài)標(biāo)志、線程持有鎖、偏向線程ID、偏向時間戳等。也稱Mrak Word
類型指針
對象指向它的類元數(shù)據(jù)的指針。虛擬機(jī)通過這個指針來確定對象是屬于哪個類的實(shí)例
對象實(shí)例數(shù)據(jù)部分
對象真正存儲的有效信息,各種類型的字段內(nèi)容。
對齊填充部分
不是必然存在的。起著占位符的作用。
對象起始地址必須是8字節(jié)的整數(shù)倍。當(dāng)對象實(shí)例數(shù)據(jù)部分沒有對齊時,就需要對齊填充了。
對象的訪問定位
對象的訪問定位目前有兩種流行的方式:
使用句柄
直接指針
復(fù)制代碼
句柄
直接指針
對比
使用句柄好處:棧中引用存儲的是穩(wěn)定的句柄地址,對象被移動時只會改變句柄中的實(shí)例數(shù)據(jù)指針,引用本身不需變化
使用直接引用好處:速度快,節(jié)省一次指針定位的時間開銷
《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀總結(jié)
以上是生活随笔為你收集整理的java 句柄 内存_Java内存区域学习的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java List最大_在java中获取
- 下一篇: java ftp 下载慢_Java实现f