簡體   English   中英

Java集合和垃圾收集器

[英]Java Collections and Garbage Collector

關於Java Web應用程序性能的一個小問題。

假設我有一個包含十個Rubrique對象的List<Rubrique> listRubriques

Rubrique包含一個產品List<product>List<product> listProducts )和一個客戶List<Client>List<Client> listClients )。

如果我這樣做,內存中究竟會發生什么:

listRubriques.clear(); listRubriques = null;

我的觀點是,因為listRubriques是空的,所以此列表之前引用的所有對象(包括listProductslistClients )很快就會被垃圾收集。 但是因為Java中的Collection有點棘手,因為我的應用程序存在相當大的性能問題,我問的問題是:)

編輯:我們現在假設我的Client對象包含List<Client> 因此,我的對象之間有一個循環引用。 如果我的listRubrique設置為null會發生什么? 這一次,我的觀點是我的客戶端對象將變得“無法訪問”並可能造成內存泄漏?

Java的實際Sun實現不時復制所有引用/生存對象。 然后,復制的空間可以再次用於內存分配。

那說你的例子會損害實際的表現。 listRubriques.clear()是不必要的(除了你在其他地方有一個對它的引用),因為listRubrique引用的所有內容都是垃圾,不再引用listRubriques。 如果變量listRubriques之后超出范圍,則listRubriques = null也可能不需要(可能因為它是局部變量,並且方法在這里結束)。

不僅不需要清除調用,因為clear訪問后來不再使用的對象的內存,訪問對象並且現代處理器將其放入緩存中。 因此,死對象明確地轉到處理器緩存 - 一些可能更有用的數據將被覆蓋用於該操作。

本文是獲取有關Java垃圾收集器的更多信息的一個很好的參考。

編輯 :對問題中的編輯作出反應:垃圾收集器(至少由Sun使用的實現)從一些根引用開始,並復制它可以從此引用到達的所有對象以及復制對象引用的對象。 所以你的循環引用對象是垃圾,因為沒有'外部'引用指向它們,內存將在垃圾收集中回收。

如果你有:

listRubriques = null;

並且沒有其他對象持有對listRubriques或其包含對象的引用,它有資格進行垃圾回收。 但是無法保證JVM何時會實際運行垃圾收集並釋放內存。 你可以打電話:

System.gc();

向JVM推薦您認為此時運行垃圾收集是一個好主意。 但即便如此,也無法保證。

也有

listRubriques.clear();

在將listRubriques設置為null之前不需要。

編輯 :為了回答有關循環引用的問題,JVM足夠聰明,可以確定整個對象圖與任何正在運行的代碼斷開連接,並且JVM將正確地確定它們都符合垃圾回收的條件。 即使在引用計數的舊時代,這一直都是如此。 現代JVM更快,更高效。 但它們不是垃圾收集任何更多的對象而不是舊的JVM。

“很快”是一個相當模糊的規范,但垃圾收集器可能沒有你想象的那么快。 實際收集對象時,很大程度上取決於GC配置和服務器負載,但可能需要一些時間,如果您的VM有足夠的可用堆和其他事情要做,那么“很快”就不會收集這些對象。 。

VM規范保證GC運行的唯一情況是,在某些時候否則會拋出OutOfMemoryError。 在拋出OutOfMemoryError之前,VM有義務嘗試至少收集這么多符合條件的對象實例,相關的內存分配請求可以成功(但是仍然不能保證收集所有符合條件的實例)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM