為何要垃圾回收
隨著程序的運行,內(nèi)存中存在的實例對象、變量等信息占據(jù)的內(nèi)存越來越多,如果不及時進(jìn)行垃圾回收,必然會帶來程序性能的下降,甚至?xí)驗榭捎脙?nèi)存不足造成一些不必要的系統(tǒng)異常。
那些要垃圾回收
根據(jù)之前的JVM內(nèi)存管理中知道,內(nèi)存主要是,堆,棧,方法區(qū),程序計數(shù)器,本地方法棧,而棧,方法區(qū),程序計數(shù)器的聲明周期是隨著線程的結(jié)束,內(nèi)存自動釋放的,所以垃圾回收主要是針對方法區(qū)和堆
何時要垃圾回收
簡而言之就是對象在內(nèi)存中“沒用了”,這需要來及回收釋放內(nèi)存,但是如何判斷對象沒有用處則比較復(fù)雜,JVM定義了強(qiáng)、軟、若、虛四種引用類型來定義對象,不同的引用類型的對象,在GC的時候有不同的處理方式
強(qiáng)引用(Strong Reference).就是為剛被new出來的對象所加的引用,它的特點就是,永遠(yuǎn)不會被回收。
軟引用(Soft Reference).JVM內(nèi)存并不緊張,這類對象可以不被回收,如緩存對象
弱引用(Weak Reference).弱引用的對象就是一定需要進(jìn)行垃圾回收的,不管內(nèi)存是否緊張
虛引用(Phantom Reference).JVM完全不會在乎虛引用,其唯一作用就是做一些跟蹤記錄,輔助finalize函數(shù)的使用
垃圾回收方式

內(nèi)存主要被分為三塊,新生代、老年代、持久代。三代的特點不同,造就了他們所用的GC算法不同
- 新生代:用于存儲新new出來的對象,一般垃圾回收回收這里,當(dāng)垃圾回收后沒有被回收的對象會放到Survivor Spaces中(為復(fù)制算法提供了專門的from-to區(qū)域)
- 老年代:用于存儲,經(jīng)過幾次垃圾回收沒被回收的對象(如緩存對象)
- 永久代:一般存儲方法區(qū)中的類信息,Class在被 Load的時候被放入PermGen space區(qū)域. 它和和存放Instance的Heap區(qū)域不同,GC(Garbage Collection)不會在主程序運行期對PermGen space進(jìn)行清理,所以如果你的APP會LOAD很多CLASS的話,就很可能出現(xiàn)PermGen space錯誤
Scavenge GC
一般情況下,當(dāng)新對象生成,并且在Eden申請空間失敗時,就會觸發(fā)Scavenge GC,對Eden區(qū)域進(jìn)行GC,清除非存活對象,并且把尚且存活的對象移動到Survivor區(qū)。然后整理Survivor的兩個區(qū)。這種方式的GC是對年輕代的Eden區(qū)進(jìn)行,不會影響到年老代。因為大部分對象都是從Eden區(qū)開始的,同時Eden區(qū)不會分配的很大,所以Eden區(qū)的GC會頻繁進(jìn)行。因而,一般在這里需要使用速度快、效率高的算法,使Eden去能盡快空閑出來。
Full GC
對整個堆進(jìn)行整理,包括Young、Tenured和Perm。Full GC因為需要對整個對進(jìn)行回收,所以比Scavenge GC要慢,因此應(yīng)該盡可能減少Full GC的次數(shù)。在對JVM調(diào)優(yōu)的過程中,很大一部分工作就是對于FullGC的調(diào)節(jié)。有如下原因可能導(dǎo)致Full GC:
· 年老代(Tenured)被寫滿
· 持久代(Perm)被寫滿
· System.gc()被顯示調(diào)用
·上一次GC之后Heap的各域分配策略動態(tài)變化