哪些內(nèi)存需要回收?什么時(shí)候回收?如何回收?
0. 哪些內(nèi)存需要回收
內(nèi)存分布
- 程序計(jì)數(shù)器:就是PC指針,程序執(zhí)行到哪里他指到哪里,唯一一點(diǎn)是每個(gè)線程有一個(gè)PC指針,是線程私有的,因?yàn)镴ava虛擬機(jī)的多線程是通過(guò)線程輪流切換并分配處理器執(zhí)行時(shí)間的方式實(shí)現(xiàn)的。
- java棧
也是線程私有的,用于存儲(chǔ)局部變量、動(dòng)態(tài)鏈接、方法入?yún)ⅰ⒎椒ǚ祷刂档?,一個(gè)方法執(zhí)行結(jié)束就是一個(gè)java棧出棧入棧過(guò)程。 - 本地方法棧
和java棧唯一區(qū)別是執(zhí)行的是native方法,java棧執(zhí)行的是java方法,native方法一般指c、c++方法 - java堆
是java虛擬機(jī)管理的最大塊內(nèi)存,是所有線程共享的一塊內(nèi)存,也是垃圾回收器管理的主要部分,gc回收說(shuō)的主要是這塊內(nèi)存 - 方法區(qū)
是各個(gè)線程共享的內(nèi)存,用于存儲(chǔ)加載的類信息、常亮、靜態(tài)常亮、編譯后的代碼等數(shù)據(jù)
上面的java堆和方法區(qū)就是gc要回收的區(qū)域
1. 什么時(shí)候回收
java堆
- 引用計(jì)數(shù)算法
給對(duì)象添加引用計(jì)數(shù)器,有地方引用它加1,引用失效減1,gc掃描到這個(gè)對(duì)象的時(shí)候如果計(jì)數(shù)器為0就回收,最大的缺點(diǎn)是兩個(gè)對(duì)象互相引用,別的地方?jīng)]有引用這兩個(gè)對(duì)象的時(shí)候就沒(méi)辦法回收這兩個(gè)對(duì)象 -
可達(dá)性分析算法
從gc Root開(kāi)始向下搜索,能到達(dá)的對(duì)象不能回收,不能到達(dá)的對(duì)象就可以回收了.
方法區(qū)
- 常量
比如字符串常量"abc",沒(méi)有任何String對(duì)象引用它,也沒(méi)有其他地方引用它,那就可以回收他 - 類
- 該類的所有實(shí)例都被回收了
- 加載該類的ClassLoader已經(jīng)被回收了
- 該類對(duì)應(yīng)的java.lang.Class對(duì)象沒(méi)有在任何地方被引用
滿足以上條件就可以回收這個(gè)無(wú)用類
如何回收?
- 標(biāo)記-清除算法
需要回收的對(duì)象標(biāo)記出來(lái),gc回收時(shí)清除一遍 - 復(fù)制算法
把內(nèi)存空間平分兩份,一份使用,需要回收時(shí)把使用的一份中未標(biāo)記的內(nèi)存復(fù)制到另一份,然后使用過(guò)的全部清除 - 標(biāo)記-整理算法
需要回收的對(duì)象標(biāo)記出來(lái),gc回收時(shí)移動(dòng)到一端,把另一端的全部清零 - 分代收集算法
把內(nèi)存分為新生代和老生代,新生代用復(fù)制算法,老生代用標(biāo)記-清除或者標(biāo)記-整理算法
