??生命不息膨桥,學(xué)習(xí)不止!
??JVM內(nèi)存模型由:堆某残、棧国撵、方法區(qū)、本地方法棧玻墅、程序計數(shù)器構(gòu)成了JVM運行時數(shù)據(jù)區(qū)介牙。
JVM內(nèi)存模型,如下圖:
Java堆內(nèi)存(Heap)
??Java堆內(nèi)存是JVM啟動時創(chuàng)建的一塊重要的內(nèi)存區(qū)澳厢,該區(qū)域是所有線程共享的區(qū)域环础。Java堆內(nèi)存主要的作用就是為所有的對象實例
和數(shù)組
分配內(nèi)存空間囚似,創(chuàng)建的對象實例和數(shù)組都被存在Java堆內(nèi)存中。
??Java堆內(nèi)存也是JVM GC收集器管理內(nèi)存區(qū)域线得,在Hotspot虛擬機中堆內(nèi)存分為兩部分新生代
和老年代
饶唤,而新生代
可劃分為eden區(qū)
和survivor區(qū)
,其中Survivor區(qū)又可分為:From
和To
兩個區(qū)域贯钩,Java堆內(nèi)存之所以會這么劃分募狂,主要是方便堆對內(nèi)存的管理。
??Java 堆內(nèi)存大小可以通過:``-Xms和-Xmx
來分配java堆內(nèi)存的最小和最大內(nèi)存角雷,可以使用-Xmn
來調(diào)整年輕代的內(nèi)存大小祸穷。
堆內(nèi)存結(jié)構(gòu),如下圖:
方法區(qū)(Method Area)
??Java方法區(qū)是JVM線程共享的一個內(nèi)存區(qū)域勺三,Java方法區(qū)主要適用于存放雷滚,被JVM加載的類型信息、常量吗坚、靜態(tài)變量祈远、即時編譯器編譯后的代碼緩存等信息。
??在JDK8以前方法區(qū)的數(shù)據(jù)都存儲在"永久代
"中商源,可以通過-XX:PermSize
和 -XX:MaxPermSize
指定JVM中的永久代(方法區(qū))的大小车份,永久代
是在JVM中實現(xiàn)的,并且永久代
被占用的內(nèi)存只有在FullGC的時候有可能被回收牡彻,而且回收的表現(xiàn)也一般躬充。正因為這樣方法區(qū)
的內(nèi)存沒有得到很好的管理,在使用的時候讨便,對方法區(qū)內(nèi)存控制不當(dāng)會出現(xiàn)java.lang.OutOfMemoryError: PermGen space
,字符串量池過大以政、靜態(tài)變量過多都會導(dǎo)致方法區(qū)內(nèi)存空間不足霸褒。例如:我們的業(yè)務(wù)需要動態(tài)通過網(wǎng)絡(luò)加載類信息,隨著時間的延長加載類的信息逐漸變多盈蛮,方法區(qū)內(nèi)存得不到回收废菱,也會出現(xiàn)OOM。
??到了JDK8抖誉,方法區(qū)的內(nèi)存通過元空間
替換掉永久代
殊轴,元空間和永久代沒有太多的區(qū)別,他們的作用都是方法區(qū)的實現(xiàn)袒炉。元空間
和永久代
的最大區(qū)別就是旁理,元空間不在虛擬機內(nèi)存中,而是直接使用本地內(nèi)存來存儲方法區(qū)數(shù)據(jù)我磁。
??在默認(rèn)情況下孽文,元空間
的大小僅受本地內(nèi)存限制驻襟,但可以通過:-XX:MetaspaceSize
(初始空間大小)和-XX:MaxMetaspaceSize
(最大空間)參數(shù)來指定元空間的大小,默認(rèn)是不限制元空間的大小的芋哭。元空間還有兩個與 GC 相關(guān)的參數(shù):
-
-XX:MinMetaspaceFreeRatio
:在GC之后沉衣,最小的元空間
剩余空間容量的百分比 -
-XX:MaxMetaspaceFreeRatio
:在GC之后,最大的元空間
剩余空間容量的百分比
JVM棧(Java Virtual Machine Stacks)
?? JVM棧是JVM線程私有的內(nèi)存區(qū)域减牺,棧的生命會周期和Java線程一樣豌习。JVM棧描述的是Java方法執(zhí)行的線程模型。每一個java方法被執(zhí)行的時候拔疚,JVM都會同步創(chuàng)建一個棧幀用于存儲局部變量表肥隆、操作數(shù)棧、動態(tài)鏈接草雕、方法出口等巷屿。
?? 每一個Java方法在被調(diào)用一直到執(zhí)行結(jié)束的過程,都會對應(yīng)著一個棧幀
在JVM棧中的入棧
到出棧
的過程墩虹。
??局部變量表
存放了編譯時期可知的JVM基本數(shù)據(jù)類型(boolean嘱巾、byte、char诫钓、short旬昭、int、 float菌湃、long袋哼、double
)、對象引用 和 returnAddress 類型宦赠。
??這些數(shù)據(jù)類型在局部變量表
中的存儲空間以局部變量槽
(Slot)來表示锻拘,其中64位長度的long
和 double
類型的數(shù)據(jù)會占用兩個變量槽,其余的數(shù)據(jù)類型只占用一個下愈。
??局部變量表
所需的內(nèi)存空間在編譯期間完成分配
纽绍,當(dāng)進入一個方法時,這個方法需要在棧幀中分配多大的局部變量空間是完全確定的势似,方法運行期間不會改變局部變量表的大小
java虛擬機棧結(jié)構(gòu):
程序計數(shù)器(Program Counter Register)
??程序計數(shù)器
是JVM線程私有的拌夏,是一塊內(nèi)存較小的空間÷囊颍可以把程序計數(shù)器
看作是當(dāng)前線程執(zhí)行字節(jié)碼行號的指示器
障簿。
??字節(jié)碼解釋器在工作的時候就是通過改變程序計數(shù)器
的值來選取下一條要執(zhí)行的字節(jié)碼指令。
??Java虛擬機的多線程是通過線程輪流切換栅迄、分配處理器執(zhí)行時間的方式來實現(xiàn)
的站故,在任何一 個確定的時刻,一個處理器都只會執(zhí)行一條線程中的指令霞篡。因此世蔗,為了線程切換后能恢復(fù)到正確的執(zhí)行位置端逼,每條線程都需要有一個獨立的程序計數(shù)器,各條線程之間計數(shù)器互不影響污淋,獨立存儲顶滩。
本地方法棧(Native M ethod Stacks)
??本地方法棧
與JVM棧
非常相似,其區(qū)別是JVM棧
為虛擬機執(zhí)行Java方法服務(wù)寸爆,而本地方法棧
則是為虛擬機使用到的本地方法服務(wù).
運行時常量池(Runtime Constant Pool)
??運行時常量池
是方法區(qū)的一部分礁鲁。Class文件中除了有類的版本、字 段赁豆、方法仅醇、接口等描述信息外,還有一項信息是常量池表(Constant Pool Table)魔种,用于存放編譯期生成的各種字面量與符號引用析二,這部分內(nèi)容將在類加載后存放到方法區(qū)的運行時常量池中。
??致此节预,JVM內(nèi)存結(jié)構(gòu)介紹結(jié)束叶摄!
??生命不息,學(xué)習(xí)不止安拟!