1、GC算法和種類算法
GC的概念ide
GC算法 引用計數法 標記清除 標記壓縮 複製算法 可觸及性 Stop-The-World GC的對象是堆空間和永久區
引用計數法優化
老牌垃圾回收算法 經過引用計算來回收垃圾 使用者 COM ActionScript3 Python
標記-清除this
標記-清除算法是現代垃圾回收算法的思想基礎。 標記-清除算法將垃圾回收分爲兩個階段:標記階段和清除階段。 一種可行的實現是,在標記階段,首先經過根節點,標記全部從根節點開始的可達對象。所以,未被標記的對象就是未被引用的垃圾對象。 而後,在清除階段,清除全部未被標記的對象。
標記-壓縮線程
標記-壓縮算法適合用於存活對象較多的場合,如老年代。 它在標記-清除算法的基礎上作了一些優化。和標記-清除算法同樣,標記-壓縮算法也首先須要從根節點開始,對全部可達對象作一次標記。 但以後,它並不簡單的清理未標記的對象,而是將全部的存活對象壓縮到內存的一端。以後,清理邊界外全部的空間。
複製算法3d
與標記-清除算法相比,複製算法是一種相對高效的回收方法 不適用於存活對象較多的場合 如老年代 將原有的內存空間分爲兩塊,每次只使用其中一塊,在垃圾回收時,將正在使用的內存中的存活對象複製到未使用的內存塊中,以後,清除正在使用的內存塊中的全部對象,交換兩個內存的角色,完成垃圾回收
分代思想code
依據對象的存活週期進行分類,短命對象歸爲新生代,長命對象歸爲老年代。 根據不一樣代的特色,選取合適的收集算法 少許對象存活,適合複製算法 大量對象存活,適合標記清理或者標記壓縮
gc算法總結對象
可觸及性blog
可觸及的 從根節點能夠觸及到這個對象 可復活的 一旦全部引用被釋放,就是可復活狀態 由於在finalize()中可能復活該對象 不可觸及的 在finalize()後,可能會進入不可觸及狀態 不可觸及的對象不可能復活 能夠回收
public class CanReliveObj { public static CanReliveObj obj; @Override protected void finalize() throws Throwable { super.finalize(); System.out.println("CanReliveObj finalize called"); obj=this; } @Override public String toString(){ return "I am CanReliveObj"; }
public static void main(String[] args) throws InterruptedException{ obj=new CanReliveObj(); obj=null; //可復活 System.gc(); Thread.sleep(1000); if(obj==null){ System.out.println("obj 是 null"); }else{ System.out.println("obj 可用"); } System.out.println("第二次gc"); obj=null; //不可復活 System.gc(); Thread.sleep(1000); if(obj==null){ System.out.println("obj 是 null"); }else{ System.out.println("obj 可用"); } } }
經驗:避免使用finalize(),操做不慎可能致使錯誤。 優先級低,什麼時候被調用, 不肯定 什麼時候發生GC不肯定 可使用try-catch-finally來替代它
根ip
棧中引用的對象 方法區中靜態成員或者常量引用的對象(全局對象) JNI方法棧中引用對象
Stop-The-World
Java中一種全局暫停的現象 全局停頓,全部Java代碼中止,native代碼能夠執行,但不能和JVM交互 多半因爲GC引發 Dump線程 死鎖檢查 堆Dump
每秒打印10條(這個是jdk6的,jdk8的gc回收停頓沒有這麼長,知道原理後續在分析)
public static class PrintThread extends Thread{ public final long starttime=System.currentTimeMillis(); @Override public void run(){ try{ while(true){ long t=System.currentTimeMillis()-starttime; System.out.println("time:"+t); Thread.sleep(100); } }catch(Exception e){ } } }
public class MyThread extends Thread{ HashMap<Long,byte[]> map=new HashMap<Long,byte[]>(); @Override public void run(){ try{ while(true){ if(map.size()*512/1024/1024>=450){ System.out.println(「=====準備清理=====:"+map.size()); map.clear(); } for(int i=0;i<1024;i++){ map.put(System.nanoTime(), new byte[512]); } Thread.sleep(1); } }catch(Exception e){ e.printStackTrace(); } } }