以上內(nèi)容不是原創(chuàng)浸锨,如有侵權(quán)榨咐,請告知。
首先明白一點(diǎn),JVM本質(zhì)上也是一個(gè)進(jìn)程運(yùn)行在操作系統(tǒng)上能扒。
C程序的存儲空間布局
正文段:這是存放CPU執(zhí)行的機(jī)器指令佣渴。通常代碼區(qū)是共享的,即其它執(zhí)行程序可以調(diào)用它初斑。
初始化數(shù)據(jù)段(數(shù)據(jù)段):存放已經(jīng)初始化的全局變量辛润、已經(jīng)初始化的靜態(tài)變量(包括全局和局部的)。
未初始化數(shù)據(jù)段:存放未初始化的全局變量和未初始化的靜態(tài)變量见秤。
棧:由編譯器自動(dòng)釋放砂竖,存放函數(shù)的參數(shù)值、局部變量等鹃答。
堆:用于動(dòng)態(tài)分配內(nèi)存乎澄,位于BSS和棧中間的地址區(qū)域。
《UNIX環(huán)境高級編程》
Java虛擬機(jī)的內(nèi)存結(jié)構(gòu)
程序計(jì)數(shù)器
- 線程私有的
- 當(dāng)前線程所執(zhí)行的字節(jié)碼的行號指示器
java虛擬機(jī)棧
- 線程私有的
- 每個(gè)方法執(zhí)行的同時(shí)會(huì)創(chuàng)建一個(gè)棧幀用于存儲局部變量表挣跋、操作數(shù)棧三圆、動(dòng)態(tài)鏈接狞换、方法出口等避咆。
- 局部變量表包括基本數(shù)據(jù)類型、對象引用(存的是對象的地址)
本地方法棧
- native方法調(diào)用
java堆
- 所有線程共享的
- 存放實(shí)例對象
- 垃圾回收收集器的主要區(qū)域(GC堆)
- 新生代和老生代()
- 可以處于物理上不連續(xù)的內(nèi)存空間
方法區(qū)
- 線程共享的
- 用于存儲已被虛擬機(jī)加載的類信息修噪、常量查库、靜態(tài)常量、及時(shí)編譯器編譯后的代碼等數(shù)據(jù)黄琼。
- 永生代
運(yùn)行時(shí)常量池
- 方法區(qū)的一部分
- 用于存放編譯期后生成的各種字面量的符號引用
來源:《深入理解Java虛擬機(jī)》
關(guān)系
上圖特別強(qiáng)調(diào)了JVM進(jìn)程模型的代碼區(qū)和數(shù)據(jù)區(qū)指的是JVM自身的樊销,而非Java程序的。普通進(jìn)程棧區(qū)脏款,在JVM一般僅僅用做線程棧围苫。JVM的堆區(qū)和普通進(jìn)程的差別是最大的,下面具體詳細(xì)說明:
首先是永久代撤师。永久代本質(zhì)上是Java程序的代碼區(qū)和數(shù)據(jù)區(qū)剂府。Java程序中類(class),會(huì)被加載到整個(gè)區(qū)域的不同數(shù)據(jù)結(jié)構(gòu)中去剃盾,包括常量池腺占、域、方法數(shù)據(jù)痒谴、方法體衰伯、構(gòu)造函數(shù)、以及類中的專用方法积蔚、實(shí)例初始化意鲸、接口初始化等。這個(gè)區(qū)域?qū)τ诓僮飨到y(tǒng)來說,是堆的一個(gè)部分怎顾;而對于Java程序來說论矾,這是容納程序本身及靜態(tài)資源的空間,使得JVM能夠解釋執(zhí)行Java程序杆勇。
其次是新生代和老年代贪壳。新生代和老年代才是Java程序真正使用的堆空間,主要用于內(nèi)存對象的存儲蚜退;但是其管理方式和普通進(jìn)程有本質(zhì)的區(qū)別闰靴。
普通進(jìn)程在運(yùn)行時(shí)給內(nèi)存對象分配空間時(shí),比如C++執(zhí)行new操作時(shí)钻注,會(huì)觸發(fā)一次分配內(nèi)存空間的系統(tǒng)調(diào)用蚂且,由操作系統(tǒng)的線程根據(jù)對象的大小分配好空間后返回;同時(shí)幅恋,程序釋放對象時(shí)杏死,比如C++執(zhí)行delete操作時(shí),也會(huì)觸發(fā)一次系統(tǒng)調(diào)用捆交,通知操作系統(tǒng)對象所占用的空間已經(jīng)可以回收淑翼。
JVM對內(nèi)存的使用和一般進(jìn)程不同。JVM向操作系統(tǒng)申請一整段內(nèi)存區(qū)域(具體大小可以在JVM參數(shù)調(diào)節(jié))作為Java程序的堆(分為新生代和老年代)品追;當(dāng)Java程序申請內(nèi)存空間玄括,比如執(zhí)行new操作,JVM將在這段空間中按所需大小分配給Java程序肉瓦,并且Java程序不負(fù)責(zé)通知JVM何時(shí)可以釋放這個(gè)對象的空間遭京,垃圾對象內(nèi)存空間的回收由JVM進(jìn)行。
JVM的內(nèi)存管理方式的優(yōu)點(diǎn)是顯而易見的泞莉,包括:第一哪雕,減少系統(tǒng)調(diào)用的次數(shù),JVM在給Java程序分配內(nèi)存空間時(shí)不需要操作系統(tǒng)干預(yù)鲫趁,僅僅在Java堆大小變化時(shí)需要向操作系統(tǒng)申請內(nèi)存或通知回收斯嚎,而普通程序每次內(nèi)存空間的分配回收都需要系統(tǒng)調(diào)用參與;第二饮寞,減少內(nèi)存泄漏孝扛,普通程序沒有(或者沒有及時(shí))通知操作系統(tǒng)內(nèi)存空間的釋放是內(nèi)存泄漏的重要原因之一,而由JVM統(tǒng)一管理幽崩,可以避免程序員帶來的內(nèi)存泄漏問題苦始。
最后是未使用區(qū),未使用區(qū)是分配新內(nèi)存空間的預(yù)備區(qū)域慌申。對于普通進(jìn)程來說陌选,這個(gè)區(qū)域被可用于堆和椑碇#空間的申請及釋放,每次堆內(nèi)存分配都會(huì)使用這個(gè)區(qū)域咨油,因此大小變動(dòng)頻繁您炉;對于JVM進(jìn)程來說,調(diào)整堆大小及線程棧時(shí)會(huì)使用該區(qū)域役电,而堆大小一般較少調(diào)整赚爵,因此大小相對穩(wěn)定。操作系統(tǒng)會(huì)動(dòng)態(tài)調(diào)整這個(gè)區(qū)域的大小法瑟,并且這個(gè)區(qū)域通常并沒有被分配實(shí)際的物理內(nèi)存冀膝,只是允許進(jìn)程在這個(gè)區(qū)域申請堆或棧空間霎挟。
以上內(nèi)容不是原創(chuàng)窝剖,如有侵權(quán),請告知酥夭。