我正在使用spring boot来开发客户端应用程序。 当运行spring boot应用程序(使用完全可执行的jar)时,x64服务器的内存使用率约为190M,x86服务器的内存使用量约为110M。
我的jvm选项是(-Xmx64M -Xms64M -XX:MaxPermSize = 64M -server), 为什么在x64服务器中,内存使用量如此之大? 如何将内存使用量减少到150M以下?
感谢。
答案 0 :(得分:11)
搜索后,我发现它已经在stackoveflow中得到答案。 Spring Boot memory consumption increases beyond -Xmx option
1. Number of http threads (Undertow starts around 50 threads per default, but you can increase / decrease via property the amount of threads needed)
2. Access to native routines (.dll, .so) via JNI
3. Static variables
4. Use of cache (memcache, ehcache, etc)
If a VM is 32 bit or 64 bit, 64 bit uses more memory to run the same application, so if you don't need a heap bigger than 1.5GB, so keep your application runnnig over 32 bit to save memory.
因为对于http服务(Tomcat或Undertow,Jetty),每次默认启动Spring引导约50个线程,并且每个线程使用1 MB(64位jvm默认设置)。
因此在64位jvm中,内存使用率是 堆(64M)+ Permgen(最大64M)+线程堆栈(1M x 50+)+本机句柄。
的引用:
答案 1 :(得分:11)
在这里玩的太晚了,但是我在Docker上的容器化Spring Boot应用程序遇到了同样的问题。在最简单的带有单个控制器和嵌入式Tomcat的Spring Boot应用程序上,您将获得的最低内存总量约为72M。投入Spring Data REST,Spring Security和一些JPA实体,您的最低要求为200M-300M。使用以下JVM选项,您可以将一个简单的Spring Boot应用程序总数减少到约7200万。
使用 -XX:+UseSerialGC
这将与分配堆内存的线程而不是专用GC线程内联执行垃圾回收
使用 -Xss512k
,这会将每个线程的堆栈内存限制为512KB,而不是默认的1MB
使用 -XX:MaxRAM=72m
,这会将JVM对堆和非堆托管内存的计算限制在此值的范围内。
除了上述JVM选项之外,您还可以在application.properties
文件中使用以下属性:
server.tomcat.max-threads=5
这会将HTTP请求处理程序线程数限制为1(默认值为50)
以下是docker stats
在具有上述限制和docker -m 72m
参数的情况下运行非常简单的Spring Boot应用程序的示例。如果我将值减小到任何比此低的值,我将无法启动该应用。
83ccc9b2156d: Mem Usage: 70.36MiB / 72MiB | Mem Percentage: 97.72%
在这里,您可以看到退出时所有本机和Java堆内存的明细。
Native Memory Tracking:
Total: reserved=1398681KB, committed=112996KB
- Java Heap (reserved=36864KB, committed=36260KB)
(mmap: reserved=36864KB, committed=36260KB)
- Class (reserved=1086709KB, committed=43381KB)
(classes #7548)
( instance classes #7049, array classes #499)
(malloc=1269KB #19354)
(mmap: reserved=1085440KB, committed=42112KB)
( Metadata: )
( reserved=36864KB, committed=36864KB)
( used=36161KB)
( free=703KB)
( waste=0KB =0.00%)
( Class space:)
( reserved=1048576KB, committed=5248KB)
( used=4801KB)
( free=447KB)
( waste=0KB =0.00%)
- Thread (reserved=9319KB, committed=938KB)
(thread #14)
(stack: reserved=9253KB, committed=872KB)
(malloc=50KB #74)
(arena=16KB #26)
- Code (reserved=248678KB, committed=15310KB)
(malloc=990KB #4592)
(mmap: reserved=247688KB, committed=14320KB)
- GC (reserved=400KB, committed=396KB)
(malloc=272KB #874)
(mmap: reserved=128KB, committed=124KB)
- Compiler (reserved=276KB, committed=276KB)
(malloc=17KB #409)
(arena=260KB #6)
- Internal (reserved=660KB, committed=660KB)
(malloc=620KB #1880)
(mmap: reserved=40KB, committed=40KB)
- Symbol (reserved=11174KB, committed=11174KB)
(malloc=8417KB #88784)
(arena=2757KB #1)
- Native Memory Tracking (reserved=1858KB, committed=1858KB)
(malloc=6KB #80)
(tracking overhead=1852KB)
- Arena Chunk (reserved=2583KB, committed=2583KB)
(malloc=2583KB)
- Logging (reserved=4KB, committed=4KB)
(malloc=4KB #179)
- Arguments (reserved=17KB, committed=17KB)
(malloc=17KB #470)
- Module (reserved=137KB, committed=137KB)
(malloc=137KB #1616)
也不要期望从中获得任何可观的性能,因为我想GC将在此设置下频繁运行,因为它没有太多可用的备用内存
答案 2 :(得分:1)
您可以使用-XX:+ UseSerialGC作为JVM参数来指定串行垃圾收集器,这是减少内存堆的最佳选择。