gpt4 book ai didi

java - 在 JUnit 中加载 spring bean 时出现 OutOfMemory 错误

转载 作者:太空宇宙 更新时间:2023-11-04 06:22:35 26 4
gpt4 key购买 nike

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

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() 方法在每个单元测试中大约运行一次,尽管有些方法会调用它很多次。前面的方法,直接声明对象(在我们转向接口(interface)方法之前)效果很好。然而,现在我们已经有了一个接口(interface),并且可能在运行时使用几种不同的实现,我们需要在运行时加载它,而 JUnit 不会配合。

我跟踪了一些现有的 stackoverflow 线程,似乎每当 Spring 动态加载一个类时,它都会将其放入 PermGen 中,但不够智能,无法识别该类的后续加载是否相同,并导致每次调用都在 PermGen 中放置一个新类,因此出现错误。建议使用“-XX:+CMSClassUnloadingEnabled”JVM 选项允许类卸载(建议是“-XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled”,但 JVM 提示“将来请使用 CMSClassUnloadingEnabled 代替 CMSPermGenSweepingEnabled”

但这并没有改变任何事情,错误仍然被抛出。

编辑:在单独的终端中观察测试套件的运行和监视 top 后,JVM 似乎没有执行任何操作来回收正在加载的类。我根据建议的评论提高了 permgen 大小,而 java 只是继续占用内存更长的时间(超过 2 GB 的值(value))。类加载和 getBean() 是否存在问题?

最佳答案

解决方案是在 xml 文件中声明 bean 时正确确定 bean 的范围:Spring 默认为单例,我猜测这就是为什么每次调用 buildMyObj() 都会创建一个新的 bean。将范围设置为原型(prototype)完全解决了我的内存问题:

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

关于java - 在 JUnit 中加载 spring bean 时出现 OutOfMemory 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27255487/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com