Java 如何减少 Spring 内存占用
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/22201620/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to reduce Spring memory footprint
提问by Kousalik
I would like to ask you HOW (or IF) is possible to reduce Spring framework's RAM footprint.
我想问你如何(或如果)可以减少 Spring 框架的 RAM 占用空间。
I created a simple helloworld app for demonstrating the issue. There are only two classes and context.xml file:
我创建了一个简单的 helloworld 应用程序来演示这个问题。只有两个类和 context.xml 文件:
Main
- class with main methodTest
- class used for simulating some "work" (printig Hello in endless loop)
Main
- 具有主要方法的类Test
- 用于模拟一些“工作”的类(在无限循环中打印你好)
context.xml
contains only this:
context.xml
仅包含以下内容:
<context:component-scan base-package="mypackage" />
Test class contains only metod called init
, called after construction:
测试类只包含称为 的方法init
,在构造后调用:
@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();
}
}
I prepared two scenarios and in both of them main
method contains only one line.
我准备了两个场景,在这两个场景中,main
方法只包含一行。
In first scenario main method does this: (new Test()).init();
App works without Spring and consumes only aprox. 8MB of RAM.
在第一个场景中,main 方法是这样做的:(new Test()).init();
App 在没有 Spring 的情况下工作,并且只消耗 aprox。8MB 内存。
In second scenario main method contains following: new ClassPathXmlApplicationContext(new String[]{"spring/context.xml"});
So the app is initialized throug Spring container and consumes aprox. 45MB of RAM !
在第二种情况下,main 方法包含以下内容:new ClassPathXmlApplicationContext(new String[]{"spring/context.xml"});
因此应用程序通过 Spring 容器初始化并消耗 aprox。45MB 内存!
Is there any way how to reduce (in best case completely get rid of) this extra memory ? So far I wasn't able to find any fitting solution.
有什么方法可以减少(最好完全摆脱)这个额外的内存?到目前为止,我无法找到任何合适的解决方案。
I don't mind if there is the extra memory consumption on startup - this is perfectly fine, but after that, I need our app to reduce it.
我不介意启动时是否有额外的内存消耗 - 这很好,但在那之后,我需要我们的应用程序来减少它。
(The story behind this question is a bit more complicated, but this is for me now the core problem.)
(这个问题背后的故事有点复杂,但这对我来说现在是核心问题。)
Thank you
谢谢
采纳答案by ARRG
First a few things which you may already know but are important to understand the situation: most of the memory your program uses is the JVM heap. The heap has an initial size when your program starts executing. Sometimes the JVM will ask the OS for more memory and increase the size of the heap. The JVM will also perform garbage collection, thus freeing space in the heap.
首先是一些您可能已经知道但对于理解情况很重要的事情:您的程序使用的大部分内存是JVM 堆。当您的程序开始执行时,堆具有初始大小。有时 JVM 会要求操作系统提供更多内存并增加堆的大小。JVM 还将执行垃圾收集,从而释放堆中的空间。
When the used heap size diminishes, memory is not necessarily released by the JVM.The oracle JVM is reluctant to do so. For example if your program uses 500 MB of ram on startup, then after garbage collection only uses 100 MB for most of its execution, you cannot assume the additional 400 MB will be given back to your OS.
当使用的堆大小减少时,JVM 不一定会释放内存。oracle JVM 不愿意这样做。例如,如果您的程序在启动时使用 500 MB 的 ram,那么在垃圾收集后大部分执行只使用 100 MB,您不能假设额外的 400 MB 将返回给您的操作系统。
Furthermore, tools like the windows task manager (and I assume unix's ps
) will display the size of all the memory that is allocated to the JVM, regardless of whether this memory is actually used or not. Tools like jvisualvmwill let you see exactly how the memory is used in your java program, and in particular what amount of heap you're actually using vs. how much is allocated.
此外,诸如 windows 任务管理器(我假设是 unix 的ps
)之类的工具将显示分配给 JVM 的所有内存的大小,而不管这些内存是否被实际使用。像jvisualvm这样的工具可以让您确切地了解内存在 Java 程序中的使用情况,特别是您实际使用的堆数量与分配的数量。
With this in mind I tested your program in the following scenarios. Note that this depends on many factors including which JVM you use, its version, and probably your OS too.
考虑到这一点,我在以下场景中测试了您的程序。请注意,这取决于许多因素,包括您使用的 JVM、其版本以及您的操作系统。
- Standard java (SE) vs Spring.
- Garbage collection (GC) vs none (NOGC) (I called the garbage collector from jvisualvm).
- Minimum heap size defined for the JVM (using -Xmx8M). This tells the JVM to only allocate 8MB on startup. The default on my system is 256MB.
- 标准 Java (SE) 与 Spring。
- 垃圾收集 (GC) 与无 (NOGC)(我从 jvisualvm 调用垃圾收集器)。
- 为 JVM 定义的最小堆大小(使用 -Xmx8M)。这告诉 JVM 在启动时只分配 8MB。我系统上的默认值是 256MB。
For each case I report the allocated heap size and used heap size. Here are my results:
对于每种情况,我都会报告分配的堆大小和使用的堆大小。这是我的结果:
- SE, NOGC, 256M : 270 MB allocated, 30 MB used
- Spring, NOGC, 256M : 270 MB allocated, 30 MB used
- SE、NOGC、256M:已分配 270 MB,已使用 30 MB
- Spring,NOGC,256M:已分配 270 MB,已使用 30 MB
These results are identical, so from your question I assume you already had a different environment than I did.
这些结果是相同的,因此根据您的问题,我假设您已经拥有与我不同的环境。
- SE, GC, 256M : 270 MB allocated, 9 MB used
- SE、GC、256M:已分配 270 MB,已使用 9 MB
Using the GC reduces heap usage, but we still have the same allocated memory
使用 GC 减少了堆的使用,但我们仍然拥有相同的分配内存
- SE, NOGC, 8M : 9 MB allocated, <5 MB used
- Spring, NOGC, 8M : 20 MB allocated, <5 MB used
- SE、NOGC、8M:已分配 9 MB,已使用 <5 MB
- Spring、NOGC、8M:已分配 20 MB,已使用 <5 MB
This is the most important result: more memory is allocated because Spring probably needs more at some point during startup.
这是最重要的结果:分配了更多内存,因为 Spring 可能在启动期间的某个时刻需要更多内存。
Conclusions:
结论:
- If you're trying to reduce heap usage, using spring should not be much of a problem. The overhead is not gigantic.
- If you're trying to reduce allocated memory, the price of using Spring, in this experiment, is steeper. But you can still configure your JVM so that it will free memory more often than the default. I don't know much about this, but jvm options such as
-XX:MaxHeapFreeRatio=70
might be a start (more here http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html#PerformanceTuning)
- 如果你想减少堆的使用,使用 spring 应该不是什么大问题。开销并不大。
- 如果你想减少分配的内存,在这个实验中使用 Spring 的代价更高。但是您仍然可以配置您的 JVM,以便它比默认设置更频繁地释放内存。我对此知之甚少,但 jvm 选项
-XX:MaxHeapFreeRatio=70
可能是一个开始(更多在这里http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html#PerformanceTuning)