詳解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 強引用的資料請關注我們其它相關文章!