如何减少Spring内存占用

时间:2014-03-05 15:11:30

标签: java spring ram

我想问你如何(或IF)可以减少Spring框架的RAM占用空间。

我创建了一个简单的helloworld应用程序来演示这个问题。只有两个类和context.xml文件:

  • Main - 使用main方法的类
  • Test - 用于模拟某些“工作”的类(无限循环中的printig Hello)

context.xml仅包含此内容:

<context:component-scan base-package="mypackage" />

测试类仅包含名为init的metod,在构造之后调用:

@Component
public class Test{

    @PostConstruct
    public void init() {
        Thread t = new Thread(new Runnable() {

            @Override
            public void run() {
                try {
                    while (true) {
                        System.out.println("Hello " + Thread.currentThread().getName());
                        Thread.sleep(500);
                    }
                } catch (InterruptedException ex) {
                    ex.printStackTrace();
                }
            }
        });
        t.start();
    } 
}

我准备了两个场景,在两个场景中main方法只包含一行。

在第一个场景中,main方法执行此操作:(new Test()).init(); 应用程序没有Spring工作,只消耗aprox。 8MB RAM。

在第二个场景中,main方法包含以下内容:new ClassPathXmlApplicationContext(new String[]{"spring/context.xml"}); 因此,应用程序通过Spring容器初始化并消耗aprox。 45MB RAM!

有什么方法可以减少(在最好的情况下完全摆脱)这个额外的内存?到目前为止,我无法找到任何合适的解决方案。

我不介意启动时是否有额外的内存消耗 - 这很好,但在那之后,我需要我们的应用来减少它。

(这个问题背后的故事有点复杂,但这对我来说现在是核心问题。)

谢谢

1 个答案:

答案 0 :(得分:30)

首先,您可能已经了解了一些事情,但了解情况很重要:程序使用的大部分内存是 JVM堆。程序开始执行时,堆具有初始大小。有时,JVM会向操作系统请求更多内存并增加堆的大小。 JVM还将执行垃圾收集,从而释放堆中的空间。

当使用的堆大小减小时,内存不一定由JVM释放。 oracle JVM不愿意这样做。例如,如果您的程序在启动时使用500 MB的ram,那么在垃圾收集仅在其大部分执行时使用100 MB时,您不能假设额外的400 MB将被返回给您的操作系统。

此外,Windows任务管理器(我假设unix的ps等工具将显示分配给JVM的所有内存的大小,无论是否实际使用此内存即可。像jvisualvm这样的工具可以让你准确地看到java程序中内存的使用方式,特别是你实际使用的堆数量与分配的数量。


考虑到这一点,我在以下场景中测试了您的程序。请注意,这取决于许多因素,包括您使用的JVM,版本以及可能的操作系统。

  • 标准java(SE)vs Spring。
  • 垃圾收集(GC)与无(NOGC)(我从jvisualvm调用垃圾收集器)。
  • 为JVM定义的最小堆大小(使用-Xmx8M)。这告诉JVM在启动时只分配8MB。我系统的默认值是256MB。

对于每种情况,我都会报告分配的堆大小和使用的堆大小。以下是我的结果:

  • SE,NOGC,256M:分配270 MB,使用30 MB
  • Spring,NOGC,256M:分配270 MB,使用30 MB

这些结果是相同的,所以根据你的问题,我假设你已经拥有了与我不同的环境。

  • SE,GC,256M:分配270 MB,使用9 MB

使用GC可以减少堆使用量,但我们仍然拥有相同的已分配内存

  • SE,NOGC,8M:已分配9 MB,<5 MB已使用
  • Spring,NOGC,8M:已分配20 MB,<5 MB已使用

这是最重要的结果:分配了更多内存,因为Spring在启动期间可能需要更多内存。

<强>结论:

  • 如果您正在尝试减少堆使用量,那么使用spring应该不是什么大问题。开销并不大。
  • 如果您正在尝试减少已分配的内存,那么在此实验中使用Spring的价格会更陡峭。但您仍然可以配置JVM,以便它比默认更频繁地释放内存。我对此知之甚少,但-XX:MaxHeapFreeRatio=70之类的jvm选项可能是一个开始(更多http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html#PerformanceTuning