繁体   English   中英

在JUnit中加载Spring bean时出现OutOfMemory错误

[英]OutOfMemory Error when loading spring beans in JUnit

我正在切换应用程序以使用spring并在运行时动态加载某些类。 通过maven运行基于JUnit的测试套件时,此更改导致一致的“ java.lang.OutOfMemory:PermGen Space”错误。 我们有大约800个测试,并且OoM被投入了大约200个测试。代码更改如下:

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()是否存在问题?

解决方案是在xml文件中声明该bean时适当地确定其范围:Spring默认为singleton,这是为什么每次调用buildMyObj()都会创建一个新的bean的原因。 将范围设置为原型可完全解决我的内存问题:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM