JVM學習筆記(七、GC1-基礎知識點)
目錄:
- 我的疑問
- 什麼是GC,為什麼要有GC
- 四種引用物件
我的疑問:
- 什麼是垃圾回收。
- 回收什麼東西。
- 怎樣回收。
- 如何回收。
本節解決前兩個問題,什麼是垃圾回收,回收什麼東西。
什麼是GC,為什麼要有GC:
GC(Gabage Collection),是垃圾回收的意思。
我們知道向c、c++是需要手動回收記憶體的,但因為記憶體處理是程式設計人員容易出現問題的地方,忘記或者錯誤的記憶體回收會導致程式或系統的不穩定甚至崩潰。
所以java作為高階語言當然會幫我忙實現了自動回收記憶體啦,回收那些不再使用的物件釋放記憶體。
那java是如何判斷物件不再使用的呢?
這裡使用了一個叫做GC Roots的東西,它其實就是一個物件的引用的集合,一個物件的所有引用都在此中。
判斷物件不再使用還有一個專業的名詞叫做可達性分析,不再使用的依據就是通過GC Roots Tracing辨別。
也就是說以GC Roots為起點,從起點開始依次往下檢索,檢索的路徑稱為ReferenceChain,當GC Roots與ReferenceChain沒有任何物件相連時則表示無物件引用。
在Java語言中,可作為GC Roots的物件包括下面幾種:
- 虛擬機器棧(棧幀中的本地變量表)中引用的物件。
- 本地方法棧中JNI(即一般說的Native方法)引用的物件。
- 方法區中類靜態屬性引用的物件。
- 方法區中常量引用的物件。
四種引用物件:
前面說到了可達性分析是通過GC Roots來分析的,而GC Roots其實就是物件引用的集合,那麼你知道物件有哪幾種引用嘛,待我一一道來。
在JDK 1.2之後,Java對引用的概念進行了擴充,將引用分為強引用(Strong Reference)、 軟引用(Soft Reference)、 弱引用(Weak Reference)、 虛引用(Phantom Reference)4種,且這4種引用強度依次逐漸減弱。
1、強引用:
強引用就是我們日常開發中最常使用的Object obj = new Object(),強引用最大的特點就是不會被GC,即使記憶體不夠了也不會GC,會丟擲OutOfMemory。
如果你想中斷強引用也很簡單,只需要obj = null即可(Effective In Java中也提到了,如果你確定此物件不再使用請將其賦為null)。
1 public class StrongRef { 2 3 public static void main(String[] args) { 4 Object obj = new Object(); 5 // 即使建立array時溢位也不會回收obj物件 6 int[] array = new int[1000000]; 7 } 8 9 }
2、軟引用:
軟引用對於強引用來說使用場景比較少,一般只會在底層原始碼或框架中才會使用。
用來描述一些還有用但並非必需的物件,系統會在即將發生OutOfMemory之前將這些應用納入回收範圍內進行二次回收,如果記憶體還不夠才會丟擲OutOfMemory。
1 public class SoftRef { 2 3 public static void main(String[] args) { 4 Object obj = new Object(); 5 SoftReference<Object> softRef = new SoftReference<>(obj); 6 // obj值為null,等待GC 7 obj = null; 8 // 重新從弱引用中獲取obj示例,如果此前發生了GC則值為null 9 Object softObj = softRef.get(); 10 System.out.println(softObj == null); 11 } 12 13 }
3、弱引用:
若應用較之軟引用更弱一些,只能存活到下一次GC之前,GC時無論記憶體夠不夠都會回收弱引用。
1 public class WakeRef { 2 3 public static void main(String[] args) { 4 WeakReference<Person> reference = new WeakReference<>(new Person("張三", 20)); 5 // 此刻還能獲取到person 6 System.out.println(reference.get()); 7 // 通知JVM回收資源 8 System.gc(); 9 // GC後person=null 10 System.out.println(reference.get()); 11 12 } 13 14 } 15 16 class Person { 17 18 public String name; 19 public int age; 20 21 public Person(String name, int age) { 22 this.name = name; 23 this.age = age; 24 } 25 26 @Override 27 public String toString() { 28 return "[name:" + name + ",age:" + age + "]"; 29 } 30 31 }
4、虛引用:
也稱為幽靈引用或者幻影引用,它是最弱的一種引用關係。
一個物件是否有虛引用的存在,完全不會對其生存時間構成影響,也無法通過虛引用來取得一個物件例項。
為一個物件設定虛引用關聯的唯一目的就是能在這個物件被收集器回收時收到一個系統通知。
1 public class PhantomRef { 2 3 public static void main(String[] args) { 4 ReferenceQueue<String> queue = new ReferenceQueue<>(); 5 PhantomReference<String> phantomRef = new PhantomReference<>(new String("hello"), queue); 6 // 即使沒有被GC調值還是為null 7 System.out.println(phantomRef.get()); 8 } 9 10 }