java中垃圾收集的方法有哪些?
一、引用計數算法(Reference Counting)
介紹:給對象添加一個引用計數器,每當一個地方引用它時,數據器加1;當引用失效時,計數器減1;計數器為0的即可被回收。
優點:實現簡單,判斷效率高
缺點:很難解決對象之間的相互循環引用(objA.instance = objB; objB.instance = objA)的問題,所以java語言並沒有選用引用計數法管理內存
二、根搜索算法(GC Root Tracing)
Java和C#都是使用根搜索算法來判斷對象是否存活。通過一系列的名為“GC Root”的對象作為起始點,從這些節點開始向下搜索,搜索所有走過的路徑稱為引用鏈(Reference Chain),當一個對象到GC Root沒有任何引用鏈相連時(用圖論來說就是GC Root到這個對象不可達時),證明該對象是可以被回收的。
在Java中哪些對象可以成為GC Root?
虛擬機棧(棧幀中的本地變量表)中的引用對象
方法區中的類靜態屬性引用的對象
方法區中的常量引用對象
本地方法棧中JNI(即Native方法)的引用對象

三、標記-清除算法(Mark-Sweep)
這是垃圾收集算法中最基礎的,根據名字就可以知道,它的思想就是標記那些要被回收的對象,然后統一回收。這種方法很簡單,但是會有兩個主要問題:
1.效率不高,標記和清除的效率都很低;
2.會產生大量不連續的內存碎片,導致以后程序在分配交大的對象時,由於沒有充足的連續內存而提前觸發一次GC動作。

四、復制算法(Copying)
為了解決效率問題,復制算法將可用內存按容量划分相等的兩部分,然后每次只使用其中的一塊,當第一塊內存用完時,就將還存活的對象復制到第二塊內存上,然后一次性清除完第一塊內存,在將第二塊上的對象復制到第一塊。但是這種方式,內存的代價太高,每次基本上都要浪費一塊內存。
於是將該算法進行了改進,內存區域不再是按照1:1去划分,而是將內存划分為8:1:1三部分,較大的那份內存叫Eden區,其余兩塊較小的內存叫Survior區。每次都會先使用Eden區,若Eden區滿,就將對象賦值到第二塊內存上,然后清除Eden區,如果此時存活的對象太多,以至於Survivor不夠時,會將這些對象通過分配擔保機制賦值到老年代中。(java堆又分為新生代和老年代)。

五、標記-整理算法(Mark-Compact)
該算法是為了解決標記-清楚,產生大量內存碎片的問題;當對象存活率較高時,也解決了復制算法的效率問題。它的不同之處就是在清除對象的時候現將可回收的對象移動一端,然后清除掉端邊界以為的對象,這樣就不會產生內存碎片。

六、分代收集算法(Generational Collection)
根據對象的存活周期的不同將內存划分為幾塊,一般就分為新生代和老年代,根據各個年代的特點采用不同的收集算法。新生代(少量存活)用復制算法,老年代(對象存活率高)“標記-清理”算法
補充:分代划分內存介紹
整個JVM內存總共划分為三代:年輕代(Young Generation)、年老代(Old Generation)、持久代(Permanent Generation)
1、年輕代:所有新生成的對象首先都放在年輕代內存中。年輕代的目標就是盡可能快速的手機掉那些生命周期短的對象。年輕代內存分為一塊較大的Eden空間和兩塊較小的Survior空間,每次使用Eden和其中的一塊Survior.當回收時,將Eden和Survior中還存活的對象一次性拷貝到另外一塊Survior空間上,最后清理Eden和剛才用過的Survior空間。
2、年老代:在年輕代經歷了N次GC后,仍然存活的對象,就會被放在老年代中。因此可以認為老年代存放的都是一些生命周期較長的對象。
3、持久代:基本固定不變,用於存放靜態文件,例如Java類和方法。持久代對GC沒有顯著的影響。持久代可以通過-XX:MaxPermSize=進行設置。