- JVM內(nèi)存模型
- JVM垃圾回收
1. JVM內(nèi)存模型

JVM內(nèi)存模型
- 線程隔離的三個(gè)區(qū):
- 程序計(jì)數(shù)器:當(dāng)前線程所執(zhí)行的行號(hào)指示器,指示運(yùn)行哪一行代碼;
- JAVA虛擬機(jī)棧:存放局部變量等信息,服務(wù)于JAVA方法;
- 本地方法棧:存放局部變量等信息,服務(wù)于本地方法;
- 線程共享的兩個(gè)區(qū):
- 方法區(qū):
存放方法運(yùn)行時(shí)的常量、靜態(tài)變量等數(shù)據(jù);
方法運(yùn)行結(jié)束后隨之釋放,可以無(wú)需垃圾回收; - JAVA堆:
存放對(duì)象實(shí)例;
垃圾回收管理的主要區(qū)域;
- 方法區(qū):
2. OOM
OutOfMemoryError 異常的簡(jiǎn)稱。
引起OOM的原因?
內(nèi)存溢出、內(nèi)存泄露。
內(nèi)存溢出:申請(qǐng)不到可用空間,需要進(jìn)行垃圾回收解決;
內(nèi)存泄露:無(wú)用的對(duì)象還繼續(xù)存活,且垃圾回收也無(wú)法將其回收。
OOM與SOF的區(qū)別?
- 如果線程請(qǐng)求的棧深度大于虛擬機(jī)所允許的最大深度,將拋出StackOverflowError;
- 如果虛擬機(jī)在擴(kuò)展棧時(shí)無(wú)法申請(qǐng)到足夠的內(nèi)存空間,則拋出OutOfMemoryError異常。
3. GC(垃圾回收)
如何判斷對(duì)象是否存活?
- 可達(dá)性分析算法:
通過一系列的成為“GC Roots”的對(duì)象作為起始點(diǎn),從這些節(jié)點(diǎn)開始向下搜索,搜索所走過的路徑成為引用鏈,當(dāng)一個(gè)對(duì)象到GC ROOTS沒有任何引用鏈相連時(shí),則證明此對(duì)象時(shí)不可用的。
可以作為GC Roots的對(duì)象:
- 虛擬機(jī)棧中引用的對(duì)象
- 本地方法棧引用的對(duì)象
-
方法區(qū)中:
- 類靜態(tài)屬性引用的對(duì)象
- 常量引用的對(duì)象
引用
- 強(qiáng)引用:
強(qiáng)引用有引用變量指向時(shí)永遠(yuǎn)不會(huì)被垃圾回收。 - 軟引用:
如果一個(gè)對(duì)象具有軟引用,內(nèi)存空間足夠,垃圾回收器就不會(huì)回收它;
如果內(nèi)存空間不足了,就會(huì)回收這些對(duì)象的內(nèi)存。 - 弱引用:
當(dāng)JVM進(jìn)行垃圾回收時(shí),無(wú)論內(nèi)存是否充足,都會(huì)回收被弱引用關(guān)聯(lián)的對(duì)象。 - 虛引用:
擁有虛引用的對(duì)象可以在任何時(shí)候被垃圾回收器回收。
Finalize方法
任何一個(gè)對(duì)象的finalize()方法都只會(huì)被系統(tǒng)自動(dòng)調(diào)用一次,如果對(duì)象面臨下一次回收,它的finalize()方法不會(huì)被再次執(zhí)行。
4. 垃圾收集算法
標(biāo)記-清除算法、 標(biāo)記-整理算法、復(fù)制算法、分代收集算法
- 標(biāo)記-清除算法:
首先標(biāo)記出所有需要回收的對(duì)象,在標(biāo)記完成后統(tǒng)一回收所有被標(biāo)記的對(duì)象。
問題:效率低、產(chǎn)生內(nèi)存碎片。 - 標(biāo)記-整理算法:
讓所有存活的對(duì)象都向一端移動(dòng),然后直接清理掉端邊界以外的內(nèi)存。 - 復(fù)制算法:
將可用內(nèi)存按照容量劃分為大小相等的兩塊,每次只使用其中的一塊。當(dāng)這塊的內(nèi)存用完了,就將還存活著的對(duì)象復(fù)制到另外一塊上面,然后再把已使用過的內(nèi)存空間一次清理掉。
實(shí)際中我們并不需要按照1:1比例來(lái)劃分內(nèi)存空間,而是將內(nèi)存分為一塊較大的Eden空間和兩塊較小的Survivor空間,每次使用Eden和其中一塊Survivor;
當(dāng)另一個(gè)Survivor空間沒有足夠空間存放上一次新生代收集下來(lái)的存活對(duì)象時(shí),這些對(duì)象將直接通過分配擔(dān)保機(jī)制進(jìn)入老年代;
不足:將內(nèi)存縮小為了原來(lái)的一半。 - 分代收集算法
把java堆分為新生代和老年代;
對(duì)新生帶使用復(fù)制算法;
對(duì)老年帶使用標(biāo)記清理或標(biāo)記整理方法。
5. 垃圾收集器
垃圾收集器關(guān)系的兩個(gè)問題:
- 停頓問題:進(jìn)行垃圾收集時(shí),必須暫停其他所有的工作線程。
- 吞吐量:就是CPU用于運(yùn)行用戶代碼的時(shí)間與CPU總消耗時(shí)間的比值。
- 三種新生代收集器
- Serial:?jiǎn)尉€程、停頓;
- ParNew:Serial的多線程版本;
- Parallel Scavenge:使用復(fù)制算法,注重吞吐量。
- 三種老年代收集器
- Serial Old:Serial的老年帶版本;
- Parallel Old:Parallel Sacvenge版本;多線程,標(biāo)記整理;
- CMS:標(biāo)記清除;并發(fā)收集、低停頓;
- 分代收集器:G1——新生代老年代都能收集
最大特點(diǎn)與優(yōu)點(diǎn):可預(yù)測(cè)的停頓。
6. 內(nèi)存分配策略
- 對(duì)象優(yōu)先在新生代Eden分配;
- 大對(duì)象直接進(jìn)入老年代;
- 長(zhǎng)期存活的對(duì)象將進(jìn)入老年代;
- 動(dòng)態(tài)對(duì)象年齡判定;
- 空間分配擔(dān)保。