爲什麼要GC
Java不像C++一樣,對於在堆上申請的空間需要調用free或者delete這樣手動釋放,而是使用gc來進行自動的釋放,對於一個應用程序來說,給定的堆的空間是一定的,如果無限的申請但是不釋放的話,就會導致oom,因此gc很重要。
什麼需要被GC
和c++一樣,在堆上申請的內存空間的對象需要在一個合適的時間釋放,回想在C++中的智能指針,往往就是在對某個對象的引用計數爲0時執行析構函數釋放對應的內存,java中也是一樣,當對於某個對象的引用爲0時會被gc。
Java的引用對象
-
強引用
一般情況下聲明的都是強引用,例如:
Person person = new Person();
注意這裏的new Person()是一個對象,是在堆上分配了一定內存大小的,而person是指向它的引用,這裏就是強引用。
對於一個對象來說,只要有強引用指向它的話,系統是肯定不會對它執行gc的。所以如果在一個函數中如上正常創建一個對象的話,只有在函數執行完之後,該對象纔回被gc,因爲變量person的生命週期到頭了,就沒有指向Person對象的引用了。對於全局變量來說,如果想釋放它的話,就需要將person = null,這樣也會去掉該對象的引用。
-
弱引用
弱引用的聲明如下
WeakReference<Person> weakref = new WeakReference<>(person);
這樣就會將指向Person對象的引用變爲弱引用了
Person person = weakref.get()
這樣又會轉換爲強引用
對於一個對象來說,如果它的所有引用都是弱引用的話就會被立刻gc
-
軟引用
軟引用的聲明如下
SoftReference<Person> softref = new SoftReference<>(person)
轉爲強引用的方法如上
對於一個對象來說,如果它的所有引用都是軟引用且當前內存空間不足時,系統會對其gc
- 虛引用
虛引用需要和ReferenceQueue聯合使用,具體如下
ReferenceQueue rq = new ReferenceQueue();
PhantomReference<Person> phantomref = new PhantomReference<>(person,rq);
關於ReferenceQueue還需要再研究一下,網上說可以用來實現當某個對象被gc時的通知,未完。