Java垃圾收集算法介紹
垃圾回收器GC(Garbage Collection)
一厦取、引用計數(shù)算法(Reference Counting)
介紹:給對象添加一個引用計數(shù)器,每當一個地方引用它時就谜,數(shù)據(jù)器加1;當引用失效時,計數(shù)器減1腰懂;計數(shù)器為0的即可被回收玻粪。
優(yōu)點:實現(xiàn)簡單隅津,判斷效率高
缺點:很難解決對象之間的相互循環(huán)引用(objA.instance = objB; objB.instance = objA)的問題,所以java語言并沒有選用引用計數(shù)法管理內存
二劲室、根搜索算法(GC Root Tracing)
Java和C#都是使用根搜索算法來判斷對象是否存活伦仍。通過一系列的名為“GC Root”的對象作為起始點,從這些節(jié)點開始向下搜索很洋,搜索所有走過的路徑稱為引用鏈(Reference Chain),當一個對象到GC Root沒有任何引用鏈相連時(用圖論來說就是GC Root到這個對象不可達時)充蓝,證明該對象是可以被回收的。
在Java中哪些對象可以成為GC Root?
- 虛擬機棧(棧幀中的本地變量表)中的引用對象
- 方法區(qū)中的類靜態(tài)屬性引用的對象
- 方法區(qū)中的常量引用對象
- 本地方法棧中JNI(即Native方法)的引用對象
三喉磁、標記-清除算法(Mark-Sweep)
首先標記出需要回收的對象谓苟,在標記完成后統(tǒng)一回收掉所有的被標記對象。
缺點:效率問題和空間問題(標記清除后會產(chǎn)生大量的不連續(xù)內存碎片协怒,內存碎片過多可能會導致程序需要分配較大對象時找不到足夠大的連續(xù)內存空間而不得不提前觸發(fā)另一次垃圾回收動作)
四涝焙、復制算法(Copying)
將內存劃分為大小相等的兩塊,每次只使用其中的一塊孕暇。當這塊內存用完了仑撞,就將還存活的對象復制到另一塊內存上赤兴,然后把已使用過的內存空間一次清理掉。
優(yōu)點:每次只對其中一塊進行GC,不用考慮內存碎片的問題隧哮,并且實現(xiàn)簡單桶良,運行高效
缺點:內存縮小了一半
注:現(xiàn)在的商業(yè)虛擬機都是用這種收集算法回收新生代。內存分為一塊較大的Eden空間和兩塊較小的Survior空間近迁,每次使用Eden和其中的一塊Survior.當回收時艺普,將Eden和Survior中還存活的對象一次性拷貝到另外一塊Survior空間上,最后清理Eden和剛才用過的Survior空間鉴竭。
五歧譬、標記-整理算法(Mark-Compact)
讓所有存活對象都向一端移動,然后直接清理掉端邊界以外的所有內存搏存。
六瑰步、分代收集算法(Generational Collection)
根據(jù)對象的存活周期的不同將內存劃分為幾塊,一般就分為新生代和老年代璧眠,根據(jù)各個年代的特點采用不同的收集算法缩焦。新生代(少量存活)用復制算法,老年代(對象存活率高)“標記-清理”算法
補充:分代劃分內存介紹
整個JVM內存總共劃分為三代:年輕代(Young Generation)责静、年老代(Old Generation)袁滥、持久代(Permanent Generation)
1、年輕代:所有新生成的對象首先都放在年輕代內存中灾螃。年輕代的目標就是盡可能快速的手機掉那些生命周期短的對象题翻。年輕代內存分為一塊較大的Eden空間和兩塊較小的Survior空間,每次使用Eden和其中的一塊Survior.當回收時腰鬼,將Eden和Survior中還存活的對象一次性拷貝到另外一塊Survior空間上嵌赠,最后清理Eden和剛才用過的Survior空間。
2熄赡、年老代:在年輕代經(jīng)歷了N次GC后姜挺,仍然存活的對象,就會被放在老年代中彼硫。因此可以認為老年代存放的都是一些生命周期較長的對象炊豪。
3、持久代:基本固定不變乌助,用于存放靜態(tài)文件溜在,例如Java類和方法。持久代對GC沒有顯著的影響他托。持久代可以通過-XX:MaxPermSize=<N>進行設置。