什么是垃圾回收機(jī)制
C/C++語言 是手動來回收堆內(nèi)存里不再使用的對象,而JAVA則是由JVM來自動回收
如何確定內(nèi)存需要被回收了
標(biāo)記 ,標(biāo)記正在使用的內(nèi)存,不在使用的內(nèi)存,其中有2種內(nèi)存
- 對象內(nèi)存回收,即堆內(nèi)存的回收,使用可達(dá)性分析算法來回收
- 方法區(qū)回收 這一節(jié)沒有細(xì)說
可達(dá)性算法
可達(dá)性算法有一個根GCRoots,然后將所有相關(guān)的對象與它相連,如果某個對象在某個時候不可達(dá)到GCroots,那么它就可以被回收
具體的算法實(shí)現(xiàn)
所有的都是基于標(biāo)記--清除這一算法的,然后有2種改進(jìn)型
- 標(biāo)記-清除 優(yōu)點(diǎn):快 缺點(diǎn):有內(nèi)存碎片問題(就是內(nèi)存雖然還有很多空間,但卻不連續(xù),實(shí)際上是不能存儲數(shù)據(jù)的)
- 標(biāo)記-復(fù)制-清除: 優(yōu)點(diǎn):解決了碎片問題 缺點(diǎn):占用空間
- 標(biāo)記-清除-整理 在1的基礎(chǔ)上,將內(nèi)存整理成連續(xù)的 缺點(diǎn):慢
具體的JVM實(shí)現(xiàn)
可以看到以上三種方法各有利弊,所以JVM實(shí)現(xiàn)的時候,在不同的場景使用不同的方法
分代收集
JVM大多數(shù)會使用分帶收集實(shí)現(xiàn),即新生代-次新生代-次次新生代--老生代
大概的算法就是
- 新建的對象放在新生代,使用標(biāo)記-清除 這種方法,速度快
- 經(jīng)歷一次GC的,給它累加一個計(jì)數(shù)器,然后放到次新生代
- 當(dāng)一個對象經(jīng)歷了數(shù)次GC,計(jì)數(shù)器累加到一定的次數(shù)時,JVM認(rèn)為他經(jīng)常使用,所以放到老生代,老生代使用標(biāo)記-清除-整理的方法
- 空間大的對象也會直接放到老生代
經(jīng)歷多少次放到老生代,多大的對象會放到老生代,這些都是可以用參數(shù)來設(shè)置的
收集器
并行收集器
跟串行收集器的區(qū)別就是新生代GC和老生代GC一起進(jìn)行,可以設(shè)置GC時間和吞吐量等值,可以自動進(jìn)行適應(yīng)性調(diào)整Eden,Surviror大小和MaxTenuringThreshold大小,感覺可以簡單理解成多線程了
吞吐量 用戶代碼運(yùn)行時間/(用戶代碼運(yùn)行時間+GC時間)
可以設(shè)置的參數(shù)
- -XX:ParallelGCThreads 設(shè)置用于垃圾回收的線程數(shù)。通常情況下可以和CPU數(shù)量相等
- -XX:MaxGCPauseMills 設(shè)置最大垃圾收集停頓時間。它是一個大于0 的證書
- -XX:GCTimeRatio 設(shè)置吞吐量大小,它是一個0-100之間的整數(shù)
- -XX:UseAdaptiveSizePolicy: 打開自使用GC策略,達(dá)到在對大小、吞吐量和停頓時間之間的平衡
ParallelScavenge和Parallel Old
服務(wù)器模式默認(rèn)使用這個并發(fā)收集器,它有年輕代和老年代兩個實(shí)現(xiàn)
并行收集器G1
JDK1.9后默認(rèn)的收集器,不區(qū)分年輕代和老年代的實(shí)現(xiàn)

截屏2019-12-07下午5.36.28.png