Java 基于spring注释的配置-内存消耗过高?

Java 基于spring注释的配置-内存消耗过高?,java,spring,jvm,spring-annotations,Java,Spring,Jvm,Spring Annotations,当我注意到我的客户机应用程序(基于Swing)上的高RAM使用率时,我开始研究它,这似乎与Spring中基于注释的配置有关。正如您将在下面的编辑中看到的,我意识到这只发生在64位JVM上 请参阅以下测试代码: 基于xml的配置 <beans ....> <bean id="xmlConfigTest" class="at.test.XmlConfigTest" /> </beans> public class XmlConfigTest exten

当我注意到我的客户机应用程序(基于Swing)上的高RAM使用率时,我开始研究它,这似乎与Spring中基于注释的配置有关。正如您将在下面的编辑中看到的,我意识到这只发生在64位JVM上

请参阅以下测试代码:

基于xml的配置

<beans ....>
     <bean id="xmlConfigTest" class="at.test.XmlConfigTest" />
</beans>

public class XmlConfigTest extends JFrame {
    public static void main(String[] args) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("config/applicationContext.xml");
        XmlConfigTest frame = (XmlConfigTest) ctx.getBean("xmlConfigTest");
        frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
        frame.setVisible(true);
    }
}
不仅需要更长的时间来打开帧,而且在启动时内存消耗会猛增到160MB,然后稳定在152MB左右,这对我来说真的很高。请记住,这只是最基本的情况,我开发的客户机应用程序atm已经占用了超过400MB的内存,这对于较旧的机器来说太多了

有人对这种行为有什么解释吗?我不明白

(使用3.1.1.1在此处发布)

编辑* 正如axtavt所建议的,我还尝试直接使用测试类作为参数来构造AnnotationConfigApplicationContext,这样就不需要进行类路径扫描。不幸的是,内存消耗没有任何变化

删除编辑2请参见编辑3

编辑3 现在,我在同一台机器(Windows7 64位)上测试了32位和64位JVM以及上面的测试程序。结果如下:

基于xml的配置:

32-Bit JVM: 16MB
64-Bit JVM: 31MB
32-Bit JVM: 17MB
64-Bit JVM: 160MB
基于注释的配置:

32-Bit JVM: 16MB
64-Bit JVM: 31MB
32-Bit JVM: 17MB
64-Bit JVM: 160MB
所以在32位JVM上,两个程序都很接近,这与我所期望的差不多。但在64位上,这是不同的。即使是第一个程序在64位上使用的内存也是原来的两倍,这似乎已经太多了。不过,这并不反对第二个程序,它在64位上使用了将近10倍的内存

编辑4
现在也在ubuntu下测试->效果相同。但仍然不知道为什么会发生这种情况。这对我来说确实是一个破坏者

构建
注释配置应用程序上下文
(提供注释类的基本包)的方式需要类路径扫描,因此它需要时间和内存也就不足为奇了


如果要避免类路径扫描,可以尝试提供精确的带注释类集(
@Component
s和
@Configuration
s),启动时,使用相应的
AnnotationConfigApplicationContext

构造函数创建大量
java.lang.reflect.Method
对象

这些对象符合垃圾收集的条件,但在应用程序中,它可能会导致太多的eden收集,从而导致启动时间过长

这些
java.lang.reflect.Method
对象中的大多数都分配到以下站点:

这些似乎是在Spring试图在
AnnotationConfigTestFrame
上找到setter时创建的,它继承了
java.awt
javax.swing
超类的许多方法。我没有仔细阅读相关代码,但作为验证该假设的快速测试,我做了以下工作:

@Service
public class AnnotationConfigTestFrame /* extends JFrame */
{
    public static void main(String[] args) throws InterruptedException
    {
        ApplicationContext ctx = new AnnotationConfigApplicationContext(AnnotationConfigTestFrame.class);

        AnnotationConfigTestFrame frame = (AnnotationConfigTestFrame) ctx
                .getBean("annotationConfigTestFrame");
//        frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
//        frame.setVisible(true);

        waitABit();
        printRuntimeStats();
        System.exit(0);
    }
}
i、 e.使
AnnotationConfigTestFrame
不继承自
javax.swing.JFrame
。现在查找bean的内存使用率相当低


这可能会为您提供进一步调试的提示。

我刚刚尝试过,并按如下方式构造它:
newannotationconfigapplicationcontext(AnnotationConfigTestFrame.class)它起作用了,没有改变内存消耗,但您能确定您使用的是哪个JVM和JVM版本吗?在(oracle)1.6.0_24和(orcale)1.7.0_03中试用过。实际上没有什么不同。我有一个建议,就是在32位和64位JVM上进行堆转储(在启动之后)。比较两个实例中创建的对象数量,并验证两种情况下是否创建了相同数量的相同类型的对象。另一个建议是在64位JVM上运行带有标志的应用程序。@Matrium I无法在Mac OS X的1.6.0!64位JVM上使用Spring 3.1.2.RELEASE重现高内存消耗。在我的机器上,
XmlConfigTest
花费了15米,但
AnnotationConfigTestFrame
只花费了5米。在类路径上或在.test的
包中有很多类吗?@Matrium我收回这一点-我可以看到Linux和OS X上的大量内存使用情况。请参阅和。这非常有用,谢谢!我想从现在起,我将对gui包使用xml配置,而不是扫描。