Java虛擬機

垃圾回收主要是回收堆內存。在垃圾回收期(GC)回收以前,須要肯定哪些對象能夠回收,有如下幾種方法:算法

  1. 引用計數算法
    原理:給對象添加一個引用計數器,每當有一個地方引用它時,計數器值就加1;當引用失效時,計數器值就減1;任什麼時候刻計數器都爲0的對象就是不可能再被使用的。這種算法效率高。不過很難解決對象之間的相互循環引用的問題。
  2. 根搜索算法(默認)
    原理:經過一系列的名爲「GC Roots」的對象做爲起始點,從這些節點開始向下搜索,搜索所走過的路徑稱爲引用鏈,當一個對象到GC Roots沒有任何引用鏈相連時,則證實此對象是不可用的。做爲GC Roots的對象包括如下幾種:
    • 虛擬機棧中的引用的對象
    • 方法區中的類靜態屬性引用的對象
    • 方法區中的常量引用的對象
    • 本地方法棧中JNI的引用的對象

引用

  • 強引用,相似"Object obj = new Object()"這種,只要強引用存在,則GC永遠不會回收被引用的對象
  • 軟引用,指還有用,可是並不是必須的對象,內存溢出以前進行回收,實現軟引用能夠經過SoftReference類,軟引用主要用戶實現相似緩存的功能,在內存足夠的狀況下直接經過軟引用取值,無需從繁忙的真實來源查詢數據,提高速度;當內存不足時,自動刪除這部分緩存數據,從真正的來源查詢這些數據。
  • 弱引用,跟軟引用同樣,不過強度比軟引用弱一些,第二次垃圾回收時回收,實現弱引用能夠經過WeakReference類,弱引用主要用於監控對象是否已經被垃圾回收器標記爲即將回收的垃圾,能夠經過弱引用的isEnQueued方法返回對象是否被垃圾回收器標記。
  • 虛引用,是最弱的一種引用關係,垃圾回收時回收,沒法經過引用取到對象值。主要用於檢測對象是否已經從內存中刪除。

垃圾收集算法

  1. 標記-清除算法:首先標記出全部須要回收的對象,在標記完成後統一回收全部被標記的對象,不過該算法有如下缺點:
    • 效率低
    • 空間問題,該算法會產生大量不連續的內存碎片,這樣致使程序在之後的運行中若是須要分配較大對象時沒法找到足夠的連續內存而觸發另外一次垃圾收集動做
  2. 複製算法:將可用內存按容量劃分大小相等的兩塊,每次只使用其中的一塊。當一塊內存用完了,就將還存活的對象複製到另一塊上面,而後再把已使用過的內存空間一次清理掉。這種算法實現簡單,效率高,不過會將可以使用的內存減小一半。若是對象存活率高就要執行較多的複製操做,將致使效率變低。目前在複製算法中,一般是將內存分爲一塊較大的Eden空間和兩塊較小的Survivor空間,每次只使用Eden和一塊Survivor。當回收時,將Eden和Survivor中還存活的對象一次性拷貝到另一塊Survivor中,最後清理使用的Eden和Survivor。而且以老年代做爲空間分配擔保,即Survivor沒法容納的對象會直接進入老年代。目前新生代主要採用這個算法。
  3. 標記-整理算法:將全部存活的對象都向一端移動,而後直接清理掉邊界之外的內存。
  4. 分代收集算法:根據對象的存活週期的不一樣將內存劃分爲幾塊,通常是分爲新生代和老年代。而後根據各個年代的特色採用最適當的收集算法。新生代一般採用複製算法,由於對象生存時間都不長。老年代通常採用"標記-清理"或者"標記-整理"算法回收,由於老年代中對象存活率高,沒有額外空間對它進行分配擔保。
相關文章
相關標籤/搜索