1. 程式人生 > 程式設計 >詳解JAVA 強引用

詳解JAVA 強引用

定義

強引用是使用最普遍的引用。如果一個物件具有強引用,那垃圾回收器寧願丟擲OOM(OutOfMemoryError)也不會回收它。

說明

不要被這個強字嚇到,以為這個引用就很厲害,其實強引用就是程式中使用的一般引用型別。舉個簡單的栗子:

String s = new String("Hello Frank!");

強可達
如果一個物件與GC Roots之間存在強引用,則稱這個物件為強可達(strong reachable)物件。

當你宣告一個變數並指向一個例項的時候,其實就是在創造一個強引用。那麼,既然叫強引用,它“強”在哪裡呢?

這主要體現在JVM進行GC的時候,只要物件有強引用與其關聯,就絕對不會對它進行回收,即使已經記憶體不足了也不會收回有強引用指向的物件。

如果你不需要使用某個物件了,可以將相應的引用設定為null,消除強引用來幫助垃圾回收器進行回收。因為過多的強引用也是導致OOM的罪魁禍首。

s = null;

顯式地設定消除引用,或已超出物件的生命週期範圍,則JVM會認為該物件不存在引用,這時就可能會回收這個物件。但是具體什麼時候收集這要取決於具體的GC演算法。

如果在一個方法的內部有一個變數s持有一個物件(Object)的強引用,那麼這個變數s儲存在棧中,而真正的引用內容(object)儲存在堆中。當這個方法執行完成後就會退出方法棧,則引用s也會被銷燬,這個object就會被回收。但是當這個s是全域性變數時,就需要在不再使用這個物件時賦值為null,因為有強引用關聯的物件是不會被垃圾回收的。

A a = new A();
B b = new B(a);
a = null;

這裡a和b是強引用,當把 a = null 時,這時 a 不再指向 A 的地址。講道理:當某個物件不再與其他引用關聯時,就會被 垃圾回收器判定為可回收,在GC中就會被回收掉。但是這裡a = null 時,A 物件不能被回收,因為還有一個B物件持有其強引用,這時候就造成了記憶體洩漏。

再看另一個會導致記憶體洩漏的栗子:

public static ArrayList<Object> list = new ArrayList<Object>();
public void stackOverflowTest(Object object){
  list.add(object);
  object = null;
}

GC回收的是不可達、弱可達或者虛可達物件,但是,在這個靜態集合類物件中,持有了物件的強引用,但是卻有可能物件已經不再使用了,所以當非靜態物件被靜態變數持有強引用的時候,最容易發生記憶體洩露,在方法中從list獲取到物件後賦值給一個變數,使用完之後將這個變數設定為null並不會釋放object引用的物件,因為list中還是持有物件的強引用。這時就造成了記憶體洩漏。

小結

所以小結一下強引用的特點:

  • 強引用就是最普通的引用
  • 可以使用強引用直接訪問目標物件
  • 強引用指向的物件在任何時候都不會被系統回收
  • 強引用可能會導致記憶體洩漏
  • 過多的強引用會導致OOM

以上就是詳解JAVA 強引用的詳細內容,更多關於JAVA 強引用的資料請關注我們其它相關文章!