2014-12-02 87 views
1

我正在切換應用程序以使用spring並在運行時動態加載某些類。當通過maven運行基於JUnit的測試套件時,這種變化導致了一致的'java.lang.OutOfMemory:PermGen Space'錯誤。我們有大約800測試和OOM被拋出約200測試的代碼更改如下:在JUnit中加載彈簧bean時發生OutOfMemory錯誤

private Obj buildMyObj() { 
    //Obj obj = MyObj(1); //Old method to get obj 
    ObjInterface obj = (ObjInterface) MyAppContext.INSTANCE.getApplicationContenxt().getBean("Obj"); 
} 

而且在XML文件中,我已經添加了以下內容:

<bean id="Obj" class="com.project.obj.ObjImplOne"> 
    <constructor-arg name="arg0" val="1"/> 
</bean> 

的buildMyObj()方法每個單元測試運行約一次,儘管有些會調用它多次。前面的方法,直接聲明對象(在我們轉到接口方法之前)工作正常。但是,現在我們已經有了一個接口並且可以在運行時使用幾個不同的實現,我們需要在運行時加載它,而JUnit不會一直玩。

我跟進了一些現有的stackoverflow線程,看來每當Spring動態加載一個類時,它會將它放入PermGen中,但不夠智能以識別該類的後續加載爲完全相同,並導致每次調用在PermGen中放置一個新類,從而導致錯誤。建議允許使用'-XX:+ CMSClassUnloadingEnabled'JVM選項(建議爲'-XX:+ CMSClassUnloadingEnabled -XX:+ CMSPermGenSweepingEnabled')來卸載類,但JVM抱怨「請使用CMSClassUnloadingEnabled替換CMSPermGenSweepingEnabled未來」

但這並沒有改變任何東西,仍然拋出的錯誤

編輯:看測試套件運行在一個單獨的終端監控頂部之後,它不會出現在JVM做任何東西回收正在加載的類。我提出每個建議的評論permgen大小,和java只是繼續聲稱更長的時間內存(超過2演出的價值)是否有類加載和getBean()的問題?

+0

PermGen的VM參數添加到您的測試 - > -XX:MaxPermSize參數=256米 – 2014-12-02 17:45:22

+0

這並沒有解決它 - 雖然增加PermGen的大小導致更多的測試正在運行,它最終像以前一樣停滯 – user2093082 2014-12-02 17:58:23

+0

你的'MyAppContext.INSTANCE.getApplicationContenxt()。getBean(「Obj」)'做了什麼?另外請注意,您必須關閉上下文,否則它將繼續進食記憶。通常使用'getBean'是代碼異味/不好的做法,應該避免,應該使用依賴注入。 – 2014-12-02 18:35:24

回答

1

解決方案是在xml文件中聲明它時正確地限定bean的範圍:Spring默認爲singleton,我猜測這是爲什麼每次調用buildMyObj()時都會創建一個新的。設置範圍爲原型完全固定我的記憶問題:

<bean id="Obj" class="com.project.obj.ObjImplOne" scope="prototype"> 
    <constructor-arg name="arg0" val="1"/> 
</bean> 
相關問題