GC是什么?為什么要有GC?
答:GC是垃圾收集的意思,內(nèi)存處理是編程人員容易出現(xiàn)問題的地方,忘記或者錯(cuò)誤的內(nèi)存回收會(huì)導(dǎo)致程序或系統(tǒng)的不穩(wěn)定甚至崩潰,Java提供的GC功能可以自動(dòng)監(jiān)測(cè)對(duì)象是否超過作用域從而達(dá)到自動(dòng)回收內(nèi)存的目的,Java語言沒有提供釋放已分配內(nèi)存的顯示操作方法。Java程序員不用擔(dān)心內(nèi)存管理,因?yàn)槔占鲿?huì)自動(dòng)進(jìn)行管理。要請(qǐng)求垃圾收集,可以調(diào)用下面的方法之一:System.gc() 或Runtime.getRuntime().gc() ,但JVM可以屏蔽掉顯示的垃圾回收調(diào)用。
垃圾回收可以有效的防止內(nèi)存泄露,有效的使用可以使用的內(nèi)存。垃圾回收器通常是作為一個(gè)單獨(dú)的低優(yōu)先級(jí)的線程運(yùn)行,不可預(yù)知的情況下對(duì)內(nèi)存堆中已經(jīng)死亡的或者長(zhǎng)時(shí)間沒有使用的對(duì)象進(jìn)行清除和回收,程序員不能實(shí)時(shí)的調(diào)用垃圾回收器對(duì)某個(gè)對(duì)象或所有對(duì)象進(jìn)行垃圾回收。在Java誕生初期,垃圾回收是Java最大的亮點(diǎn)之一,因?yàn)榉?wù)器端的編程需要有效的防止內(nèi)存泄露問題,然而時(shí)過境遷,如今Java的垃圾回收機(jī)制已經(jīng)成為被詬病的東西。移動(dòng)智能終端用戶通常覺得iOS的系統(tǒng)比Android系統(tǒng)有更好的用戶體驗(yàn),其中一個(gè)深層次的原因就在于Android系統(tǒng)中垃圾回收的不可預(yù)知性。
補(bǔ)充:垃圾回收機(jī)制有很多種,包括:分代復(fù)制垃圾回收、標(biāo)記垃圾回收、增量垃圾回收等方式。標(biāo)準(zhǔn)的Java進(jìn)程既有棧又有堆。棧保存了原始型局部變量,堆保存了要?jiǎng)?chuàng)建的對(duì)象。Java平臺(tái)對(duì)堆內(nèi)存回收和再利用的基本算法被稱為標(biāo)記和清除,但是Java對(duì)其進(jìn)行了改進(jìn),采用“分代式垃圾收集”。這種方法會(huì)跟Java對(duì)象的生命周期將堆內(nèi)存劃分為不同的區(qū)域,在垃圾收集過程中,可能會(huì)將對(duì)象移動(dòng)到不同區(qū)域:
- 伊甸園(Eden):這是對(duì)象最初誕生的區(qū)域,并且對(duì)大多數(shù)對(duì)象來說,這里是它們唯一存在過的區(qū)域。
- 幸存者樂園(Survivor):從伊甸園幸存下來的對(duì)象會(huì)被挪到這里。
- 終身頤養(yǎng)園(Tenured):這是足夠老的幸存對(duì)象的歸宿。年輕代收集(Minor-GC)過程是不會(huì)觸及這個(gè)地方的。當(dāng)年輕代收集不能把對(duì)象放進(jìn)終身頤養(yǎng)園時(shí),就會(huì)觸發(fā)一次完全收集(Major-GC),這里可能還會(huì)牽扯到壓縮,以便為大對(duì)象騰出足夠的空間。
一個(gè)系統(tǒng),定時(shí)任務(wù)超級(jí)多,但是每個(gè)定時(shí)任務(wù)都很短,在JVM優(yōu)化上,應(yīng)該怎么配置才能達(dá)到性能最優(yōu)
把新生代的那塊內(nèi)存設(shè)置大一點(diǎn)..
s0和s1區(qū)交換區(qū)比例

如何確定垃圾?
- 引用計(jì)數(shù) ×
- 從垃圾回收的根出發(fā)可見
垃圾回收根節(jié)點(diǎn)
- 局部變量
- 靜態(tài)變量
- Native方法所引用的對(duì)象
- 活動(dòng)線程,等待中的Monitor(wait,notify,synchronized)
現(xiàn)在jvm采用分代回收機(jī)制,簡(jiǎn)單來說就是分為新生代和老生代,老生代內(nèi)存空間比新生代大;大部分新對(duì)象都會(huì)優(yōu)先分配到新生代,當(dāng)新生代空間滿了會(huì)發(fā)起一次Minor GC。而新分配的大對(duì)象或者在新生代空間里存活很久的對(duì)象會(huì)被放到老生代里,老生代空間滿了會(huì)發(fā)起Major GC,但由于老生代里的對(duì)象生命周期比較長(zhǎng)加上Major GC速度比Minor GC慢很多,所以發(fā)生在老生代的Major GC相對(duì)會(huì)比Minor GC少很多。因此垃圾能不能被立即回收,要看垃圾的大小,它所處在的空間和當(dāng)前所處空間是否已滿才能基本確定。
Java分代垃圾回收算法
基礎(chǔ)假設(shè):大部分對(duì)象只存在很短的時(shí)間
將內(nèi)存分為新生代,老生代
將新生代分為Eden,Survivor1,Survivor2





新生代中 存活一定次數(shù)會(huì)被轉(zhuǎn)入老生代
Major/Full GC 會(huì)對(duì)老生代做GC
老生代GC采用Compact算法(標(biāo)記、壓縮)
參數(shù)配置:
- -XX: NewRatio 老生代/新生代比例,默認(rèn)2
- -XX: SurvivorRatio Eden/Survivor比例,默認(rèn)8
- -XX: MaxTenuringThreshold 新生代轉(zhuǎn)至老生代閾值,默認(rèn)15
PermGen Space
Permanent Generation 持久代
- 放置ClassLoader讀進(jìn)來的Class,除系統(tǒng)Class外
- 放置String.intern后的結(jié)果
- 易出現(xiàn)OutOfMemoryError:PermGen Space
- 使用 -XX: MaxPermSize調(diào)整
- Java 1.8使用Metaspace,取消持久代
- String.intern的結(jié)果被放入堆
- Metaspace默認(rèn)不設(shè)限制,使用系統(tǒng)內(nèi)存
垃圾回收在什么時(shí)候運(yùn)行?
內(nèi)存分配失敗時(shí)候,System.gc()
垃圾回收對(duì)什么對(duì)象進(jìn)行回收?
從垃圾回收的根節(jié)點(diǎn)出發(fā),順著引用關(guān)系的對(duì)象去找,找不到的對(duì)象進(jìn)行垃圾回收
垃圾回收算法對(duì)內(nèi)存劃分了哪些區(qū)域
新生代、老生代、持久代(MetaSpace),新生代又分為Eden,S1,S2
新生代采用了拷貝的方法,Eden+s -> s,存活時(shí)間久的話就放到老生代,
老生代采用的Compact算法,MetaSpace放一些class Object
垃圾回收的調(diào)試
獲取信息
-verbose:gc
-XX:+HeapDumpOnOutOfMemoryError
-XX:+PrintGCDetails -Xloggc:<GC-log-file-path>
Spring Actuator
查看信息
官方: visualvm,jmap
Eclipse Memory Analyzer(MAT)
在線: gceasy.io fastthread.io