引用計數器算法GC存在的問題是?html
描述:引用計數器法給對象中添加一個引用計數器,沒當一個地方引用它,計數器就加一,引用失效時減一,任何引用計數器爲0的對象就是不可能再被使用的對象。java
引用計數器算法的效率也比較高,主流的JVM裏面並無選用引用計數器來管理內存,其中最主要的問題是不能解決對象之間循環引用的問題。算法
java是經過可達性分析來判斷對象是否存活,這個算法的基本思路是經過一系列的稱爲「GC Roots」的對象爲起始點,從這些節點向下搜索,搜索全部的路徑稱爲引用鏈;引用鏈不能到達的對象節點是GC須要回收的。緩存
在java語言中可被稱爲「GC Roots」的對象包括下面幾個方面:bash
不管是引用計數器仍是可達性分析判斷的標準都是對象是否引用。jvm
在jdk1.2後,java對引用進行了擴充,將引用分爲強引用 、軟引用、弱引用、虛引用4種,強弱依次遞減。性能
public class Main {
public static void main(String[] args) {
new Main().fun1();
}
public void fun1() {
Object object = new Object();
Object[] objArr = new Object[1000];
}
}
複製代碼
import java.lang.ref.SoftReference;
public class Main {
public static void main(String[] args) {
SoftReference<String> sr = new SoftReference<String>(new String("hello"));
System.out.println(sr.get());
}
}
複製代碼
public class Main {
public static void main(String[] args) {
WeakReference<String> sr = new WeakReference<String>(new String("hello"));
System.out.println(sr.get());
System.gc(); //通知JVM的gc進行垃圾回收
System.out.println(sr.get());
}
}
複製代碼
ReferenceQueue<String> queue = new ReferenceQueue<String>();
PhantomReference<String> pr = new PhantomReference<String>(new String("hello"), queue);
System.out.println(pr.get());
複製代碼
如何利用軟引用和弱引用解決OOM問題優化
前面講了關於軟引用和弱引用相關的基礎知識,那麼到底如何利用它們來優化程序性能,從而避免OOM的問題呢?spa
下面舉個例子,假若有一個應用須要讀取大量的本地圖片,若是每次讀取圖片都從硬盤讀取,則會嚴重影響性能,可是若是所有加載到內存當中,又有可能形成內存溢出,此時使用軟引用能夠解決這個問題。線程
設計思路是:用一個HashMap來保存圖片的路徑 和 相應圖片對象關聯的軟引用之間的映射關係,在內存不足時,JVM會自動回收這些緩存圖片對象所佔用的空間,從而有效地避免了OOM的問題。在Android開發中對於大量圖片下載會常常用到。
要宣告一個對象死亡,至少經歷兩次標記過程:若是進行可達性分析時沒有到達的引用鏈,將會作第一次標記,此處須要進行一次篩選,條件是有必要執行finalize()方法,當對象沒有覆蓋finalize(),或者已經被jvm調用,這兩種狀況稱爲「沒有必要執行」;若是對象被判斷有必要執行,會被放置在一個F-Queue隊列,稍後有優先級低的線程進行第二次標記,若是對象finalize從新進行了引用,那麼將會移出回收隊列,不然會被進行垃圾回收。
判斷一個類須要回收的條件:
參考書籍: 深刻理解jvm
引用博客: https://www.cnblogs.com/dolphin0520/p/3784171.html