2009-07-14 89 views
1

我的開發人員和我有一個問題,當我們不希望他們成爲垃圾收集在我們的應用程序中的對象。我們正在使用Java和Weblogic 10g3。我們正在編寫一個單例模式來處理我們所有的JMS連接。爲什麼這是垃圾收集

有涉及兩類:

public class JMSObject { 
... 
private MessageProducer _producer; 
private MessageConsumer _consumer; 
... 
// standard get/set procs... etc. 
} 

public class JMSFactory { 
... 
// Hashmap sessions with key == ConnectionFactory Name 
    Hashmap<String, List<Session>> _sessions; 

// Hashmap of JMSObjects with key == ConnectionFactory Name + JMS Queue Name 
    Hashmap<String, List<JMSObject>> _jmsobjects; 
... 
// standard get/set & necessary sington functions 
} 

的servlet的init方法調用JMSFactory singlton方法,任何新的會話被放置在_sessions HashMap和新的MessageConsumer /的MessageProducer被創建爲JMSObject並放置在_jmsobjects Hashmap中,在適當的List中。

問題是,當系統運行時,列表中的JMSObjects會在一段時間後收集垃圾(有時在幾個小時後的其他時間5分鐘內)。我們查看了幾天,但找不到任何JMSObjects被收集的理由。由於JMSFactory有一個引用他們爲什麼gc會摧毀他們?

在我們通過改變類如下固定它的端部(不改變方法的接口):

public class JMSObject { 
... 
private List<MessageProducer> _producers; 
private List<MessageConsumer> _consumers; 
... 
// standard get/set procs... etc. 
} 

public class JMSFactory { 
... 
// Hashmap sessions with key == ConnectionFactory Name 
    Hashmap<String, List<Session>> _sessions; 

// Hashmap of JMSObjects with key == ConnectionFactory Name + JMS Queue Name 
    private Hashmap<String JMSObject> _jmsobjects; 
... 
// standard get/set & necessary sington functions 
} 

在測試JMSObjects到目前爲止未被gc'ed。它已經運行了2天。

有人可以解釋爲什麼間接引用導致JMSObject被gc'ed?以及爲什麼在_sessions Hashmap中的會話沒有得到gc'ed?它與Sessions是否構建在Javax類型中並且JMSObject是我們寫的東西有什麼關係?

+0

當JMSObject被垃圾回收時,我認爲它的大小保持不變,但是當你嘗試讀取它時會得到`null`s? – 2009-07-14 03:18:38

+0

@Jack Leow,是NullPointerException ... :-( – beggs 2009-07-14 04:33:06

回答

2

我想我知道你的問題是什麼,這是我後來遇到的問題(在WebLogic 6上)。我相信這與WebLogic的動態類重新加載有關,即使您不在開發環境中,WebLogic似乎也會這樣做(我猜web.xml有些被某些服務或某種東西所觸動)。

我們的情況發生了什麼,就像你一樣,我們有一個對象的單個實例,它被定義爲某個類的靜態變量,就像你一樣,它由一個servlet初始化,它具有啓動時加載參數集。當WebLogic認爲有變化時,它通過垃圾收集類加載器(很好)但是重新加載webapp,它不會重新初始化所有標記爲「load-on-startup」的servlet(在我們的例子中,以及我猜你的是,servlet除了初始化靜態變量,沒有映射到它之外,沒有其他用途,所以它不能被調用,靜態變量被GCed,但不被重新初始化,並且服務器需要被重新啓動

在我們的例子中,我們的解決方案是在靜態初始化器中初始化靜態變量,原始開發者使用servlet初始化變量,因爲他想要一些servlet上下文信息,如果你真的沒有必要的話。需要上下文信息,你可以嘗試在ServletContextListener中進行初始化。

5

由於JMSFactory有一個引用他們爲什麼gc會摧毀他們?

那麼,在這一點上,任何對象仍然保留引用JMSFactory?

典型的單件模式保持在一個靜態成員的參考singleton對象:

public class Singleton { 
    private static Singleton instance = new Singleton(); 

    private Singleton() { 
     //constructor... 
    } 

    public static Singleton getInstance() { return instance; } 
} 

這是不是你下的格局?從你的帖子中提供的代碼是不可能告訴你的,因爲你遺漏了實際的單身代碼...

(順便說一句,使用單身人士來說這樣的事情聽起來像會引起痛苦,除了很難測試。請參閱Singletons Are Pathlogical Liars

+0

@matt b ...是的,事情是靜態的,略有不同的代碼(我們在構造函數中實例化單例,但變量是靜態的)有趣的文章,感謝鏈接 – beggs 2009-07-14 04:38:22

0

您說_sessions映射中的會話不是GC'd,但JMSObjects不是。我懷疑這是因爲它是你寫的東西。這聽起來像是JMSFactory本身正在被收集(即singleton沒有正確實現),或者是從地圖中刪除了鍵。無論哪種情況,JMSObjects都有資格使用GC,但會話對象不會因爲該列表仍然有對它們的引用。

1

沒有所有的代碼,這是一個棘手的問題要解決。但有些工具可以幫助你。

嘗試此鏈接:http://blog.emptyway.com/2007/04/02/finding-memory-leaks-in-java-apps/ 它提供了有關使用jhat和jmap的信息。儘管文章是爲了查找內存泄漏而編寫的,但它提供了有關如何跟蹤對象引用的信息。也許你可以追查爲什麼你的參考文獻正在消失。

0

任何加載JMSFactory的類加載器都被卸載,導致JMSFactory類被GC化(包括單例實例),從而釋放HashMaps及其內容?