我的問題是,如果在垃圾收集階段,所有的 「死」 的對象被刪除從記憶還是其中一些生存?爲什麼一個「死」的對象在垃圾收集階段生存?
所有當前的HotSpot GC都是世代收藏家。從維基百科報價:
「經驗已經觀察到,在許多程序,最近創建的對象也是那些最有可能迅速成爲不可達(被稱爲嬰兒死亡率或代假設)分代GC (也被稱爲短暫GC)將對象劃分爲幾代,並且在大多數週期中,將僅將一代子集的對象放入初始白色(有瑕疵)集合中。此外,運行時系統通過觀察創建和覆蓋引用當垃圾收集器運行時,它可以使用這些知識來證明初始白集中的一些對象在不必遍歷整個引用樹的情況下是不可訪問的。 sis成立,這會導致更快的收集週期,同時還能收回大部分無法訪問的對象。「
這對於您的問題意味着什麼,大多數GC循環只收集年輕一代的垃圾對象。最老一代的垃圾對象可以經歷多個GC循環...直到最終收集到老一代。 (而在新的G1 GC,顯然是老一代收集了一下,在一個時間...它甚至可以進一步延遲迴收)
其他原因(名義上)不可達的對象生存包括:
無法訪問的對象(未執行的)終結器在GC完成後由垃圾收集器附加到終止隊列以供處理。
軟,弱或幻影引用的對象實際上仍然可以訪問,GC完成後由其各自的引用隊列管理器處理。
憑藉JNI全局引用等可訪問的對象。 (謝謝@ bestss)
存在各種隱藏的引用關聯實例,它們的類和它們的類加載器。
有一個從內部實例到其外部實例的隱藏引用。
對於表示其字符串文字的intern'd String對象,存在從類的隱藏引用。
然而,這些都是可訪問性的定義的所有後果:
「A可及對象是可以從任何活動線程的任何潛在的持續的計算進行訪問的對象。」 - JLS 12.6.1
這也是值得注意的是,對於GC規則到處都有保守的元素。他們說,一個可到達的對象不會被刪除,但他們並不會說(嚴格地說)不可達的對象將被刪除。這允許在不能訪問對象但運行時系統無法確定的情況下。
你的後續問題:
然而,假定垃圾收集器能達到所有的「死」的對象,我在想,如果有申報,參考,使用非關聯化的方式等等。一個對象,即使它「死」,它也會跳過刪除階段。
「死」不是一個明確定義的術語。如果垃圾收集器可以訪問這些對象,則它們通過定義可以被訪問。當它們仍然可以到達時,它們不會被刪除。
如果它們都是死的並且可到達(無論「死」是什麼意思!),那麼它們可達的事實意味着它們不會被刪除。
你提出的建議沒有意義。
我在想可能屬於類的靜態方法或內部類或類似的東西可能會因爲某些原因保存在內存中,即使它們沒有引用它們。這種情況可能嗎?
靜態方法沒有引用......除非它們碰巧在調用堆棧上。然後局部變量可能像其他方法調用一樣包含引用。正常可達性規則適用。
只要類本身存在,靜態字段就是GC根。正常可達性規則適用。
從GC的角度來看,內部類的實例與其他類的實例沒有什麼不同。可以在內部類實例中引用外部類實例,但會導致正常的可達性。
總之,可達性有一些意想不到的「原因」,但它們都是可達性定義的邏輯結果。
垃圾收集完成後,爲什麼會有_dead_對象存活。究竟。它不會。在JVM執行GC之後會有一個標準,緊接着,不會是一個死對象。 – Nishant 2011-03-18 09:17:39
它不完全關於refcounting - 對象的「島嶼」也被收集。 Nishant是對的 - 收集死者的物品。期間 – kostja 2011-03-18 09:22:52
@Nishant:它比一個有資格獲得GC的對象更容易成爲一個GC。特別適用於代GC:如果任職空間中的對象符合條件,並且JVM在eden空間中執行GC,那麼符合條件的對象將在後續執行。 – 2011-03-18 12:32:54