摘要: 原創(chuàng)出處 https://peijie-sh.github.io 歡迎轉(zhuǎn)載楣嘁,保留摘要,謝謝!
在JVM中顷啼,內(nèi)存主要被分為5類
JVM內(nèi)存結(jié)構(gòu).jpg
堆Heap
- 虛擬機(jī)內(nèi)存管理中最大的一塊內(nèi)存空間。
- 存放關(guān)鍵字
new
創(chuàng)建的對(duì)象實(shí)例和數(shù)組昌屉。 - 堆內(nèi)存被所有線程共享钙蒙。
- 這塊內(nèi)存區(qū)由
JVM
(Java虛擬機(jī))自己管理。當(dāng)使用new創(chuàng)建對(duì)象時(shí)间驮,不必指定分配空間的大小躬厌,JVM
會(huì)動(dòng)態(tài)自動(dòng)分配一塊區(qū)域;在程序執(zhí)行過程中竞帽,沒有指向此對(duì)象的引用時(shí)扛施,此對(duì)象就被標(biāo)記為可被回收狀態(tài),將由GC
(垃圾回收器)在一個(gè)不確定的時(shí)間自動(dòng)回收屹篓,釋放所占的內(nèi)存空間疙渣。 - 從內(nèi)存回收的角度看,垃圾收集器大都基于分代收集算法堆巧,所以堆一般分為
新生代
和老年代
妄荔,更細(xì)致可劃分為:Eden空間
泼菌,From Survivor空間
,To Survivor空間
懦冰。
虛擬機(jī)棧VM Stack
- 存放8種基本類型的數(shù)據(jù)和對(duì)象引用(不是對(duì)象)灶轰。
- 每個(gè)線程有自己的單獨(dú)的棧。
- 先進(jìn)后出刷钢,后進(jìn)先出笋颤。
- 因?yàn)橹饕娣呕绢愋蛿?shù)據(jù)變量,所以分配空間比堆快内地。當(dāng)超出變量的作用域伴澄,將由編譯器立即釋放空間。
本地方法棧Native Method Stack
- 與
虛擬機(jī)棧
類似阱缓,虛擬機(jī)棧
為虛擬機(jī)調(diào)用Java方法服務(wù)非凌,本地方法棧
為虛擬機(jī)調(diào)用Native方法服務(wù)。 - 在HotSpot虛擬機(jī)實(shí)現(xiàn)中荆针,
虛擬機(jī)棧
和本地方法棧
被合并為一個(gè)區(qū)域敞嗡。
程序計(jì)數(shù)器 Program Counter Register
一塊較小的內(nèi)存空間,可看作是當(dāng)前線程所執(zhí)行的字節(jié)碼的 行號(hào)指示器航背。
通過改變計(jì)數(shù)器的值來選取下一條需要執(zhí)行的字節(jié)碼指令喉悴。(分支、循環(huán)玖媚、跳轉(zhuǎn)箕肃、異常處理、線程恢復(fù)等)基礎(chǔ)功能都依賴與其完成今魔。
特點(diǎn):
- 線程私有:因?yàn)?Java 虛擬機(jī)的多線程是通過 線程輪流切換 并 分配處理器執(zhí)行時(shí)間 來實(shí)現(xiàn)的勺像,在某一時(shí)刻,只會(huì)執(zhí)行一條線程错森。因此吟宦,為了線程切換后能恢復(fù)到正確的執(zhí)行位置,每條線程都需要有一個(gè)獨(dú)立的程序計(jì)數(shù)器涩维。
- 無內(nèi)存溢出:如果線程正在執(zhí)行的是一個(gè) Java 方法殃姓,這個(gè)計(jì)數(shù)器記錄的是正在 執(zhí)行的虛擬機(jī)字節(jié)碼指令的地址;如果正在執(zhí)行的是 Native 方法激挪,這個(gè)計(jì)數(shù)器值則為空(Undefined)。此內(nèi)存區(qū)域是唯一一個(gè)在 Java 虛擬機(jī)程序規(guī)范中沒有規(guī)定任何 OutOfMemoryError 情況的區(qū)域锋叨。
方法區(qū)Method Area
- 跟堆一樣垄分,被所有的線程共享。
- 是一個(gè)內(nèi)存邏輯區(qū)域娃磺,用于存儲(chǔ)已被虛
擬機(jī)加載的類信息薄湿、常量、靜態(tài)變量、即時(shí)編譯器編譯后的代碼等數(shù)據(jù)豺瘤。
運(yùn)行時(shí)常量池Runtime Constant Pool
- 方法區(qū)的一部分吆倦。
- Class文件中除了有類的版本、字段坐求、方法蚕泽、接口等描述信息外,還有一項(xiàng)信息是常量池桥嗤,用于存放編譯期生成的各種字面量和符號(hào)引用须妻,這部分內(nèi)容將在類加載后進(jìn)入方法區(qū)的運(yùn)行時(shí)常量池中存放。
直接內(nèi)存Direct Memory
直接內(nèi)存不是虛擬機(jī)運(yùn)行時(shí)數(shù)據(jù)區(qū)的一部分泛领,也不是Java虛擬機(jī)規(guī)范中定義的內(nèi)存區(qū)域荒吏。
但是這部分內(nèi)存也被頻繁地使用渊鞋,而且也可能導(dǎo)致OutOfMemoryError異常出現(xiàn)绰更。
在JDK 1.4中新加入了NIO(New Input/Output)類,引入了一種基于通道(Channel)與緩
沖區(qū)(Buffer)的I/O方式锡宋,它可以使用Native函數(shù)庫(kù)直接分配堆外內(nèi)存儡湾,然后通過一個(gè)存儲(chǔ)
在Java堆中的DirectByteBuffer對(duì)象作為這塊內(nèi)存的引用進(jìn)行操作。這樣能在一些場(chǎng)景中顯著
提高性能员辩,因?yàn)楸苊饬嗽贘ava堆和Native堆中來回復(fù)制數(shù)據(jù)盒粮。