本章內容是對《深刻理解Java虛擬機:JVM高級特性和最佳實踐》的理解和歸納。java
前文中咱們講過了類加載器和雙親委派,那麼接下來介紹的就是GC垃圾回收機制。git
在此以前咱們須要知道GC回收機制回收的是什麼?他們的存儲形式是什麼樣的?等等一系列問題。因此引入了內存模型的概念。 github
5大區域各自的做用:算法
Object
做爲全部類的父類以他建立一個對象,將涉及哪些區域的變更呢?緩存
Object obj = new Object();
複製代碼
①、Object obj表示一個本地引用,存儲在虛擬機棧的本地變量表中,表示一個reference類型數據; ②、new Object()做爲實例對象數據存儲在堆中,另外還記錄了Object類的類型信息(接口、方法、field、對象類型等)的地址,這些地址所執行的數據存儲在方法區中;框架
既然要垃圾回收,那到底要回收的是哪些東西呢? 上文中Object
類的舉例,已經有必定的苗頭了。 在方法區中的數據,是從一開始就要求被加入的,那麼回收掉他們不免會出現各類問題。而像Object
這樣的類,只在一段時間內須要被使用,也就不免會成爲多出來的碎片,也就成了典型的「佔着茅坑不拉屎」的了。 因此,顯而易見,咱們要回收的就是這麼一類垃圾數據了,而GC回收器回收的也就是這種new
出來之後沒用了的數據了。工具
一個對象被引用時加一,被去除引用時減一。那麼當數值爲0時,這個引用就成爲了一個垃圾。 問題,若是存在循環引用時,就不會結束引用。post
// A類持有B的引用
public class A {
B b;
}
// B類一樣持有A的引用
public class B {
A a;
}
// 具體使用
public class Main {
public static void main(String[] args) {
A a = new A();
B b = new B();
a.b = b;
b.a = a;
}
}
複製代碼
像上述的代碼中,引用計數就徹底沒法進行斷定。性能
經過對一類的GC Roots
鏈表遍歷,經過可達性來斷定是否爲垃圾。 GC Roots通常包括以下:學習
這是一個應用於新生代內存整理的方法。 由於新生代的Eden區是一個連續的內存空間,經過遍歷,把這個內存空間的消亡的對象刪去,活躍的對象們從新放入一個新的空白內存空間中。 也就是To Space和From Space的相互交換。 存在問題:內存摺半。
這是一個應用於老年代內存整理的方法。
如圖所示,搜索出活躍的對象,清除消亡對象。 存在問題:會產生空間碎片。
這是一個應用於老年代內存整理的方法。
比標記清理算法多一點,他須要排序。 存在問題:用性能換取空間碎片的整理。
Java引用的分類主要也是響應了回收器的存在,通常分爲如下四類:
new
實例化的對象,這類引用GC回收器寧肯溢出,也不會回收。public class Main {
public static void main(String[] args) {
SoftReference<String> sr = new SoftReference<String>(new String("SoftReference"));
System.out.println(sr.get());
}
}
複製代碼
public class Main {
public static void main(String[] args) {
WeakReference<String> sr = new WeakReference<String>(new String("WeakReference"));
System.out.println(sr.get());
// gc回收後再次查看效果
System.gc();
System.out.println(sr.get());
}
}
複製代碼
上面三種講的很清楚了,可是這個虛引用到底有什麼用呢? 它的做用在於跟蹤垃圾回收過程,在對象被收集器回收時收到一個系統通知。 當垃圾回收器準備回收一個對象時,若是發現它還有虛引用,就會在垃圾回收後,將這個虛引用加入引用隊列,在其關聯的虛引用出隊前,不會完全銷燬該對象。 因此能夠經過檢查引用隊列中是否有相應的虛引用來判斷對象是否已經被回收了。
以上就是個人學習成果,若是有什麼我沒有思考到的地方或是文章內存在錯誤,歡迎與我分享。
相關文章推薦: