如何减少Spring启动内存的使用?

Hai*_* Li 16 java memory spring-boot

我正在使用spring boot来开发客户端应用程序.当运行spring boot应用程序(使用完全可执行的jar)时,x64服务器中的内存使用率约为190M,x86服务器中的内存使用率约为110M.

我的jvm选项是(-Xmx64M -Xms64M -XX:MaxPermSize = 64M -server),为什么在x64服务器中,内存使用量如此之大?如何减少150M以下的内存使用量?

谢谢.

CCo*_*Cob 26

这里游戏的后期不多,但我在Docker上遇到了容器化的Spring Boot应用程序.在最简单的Spring Boot应用程序中,使用单个控制器和嵌入式Tomcat,您将获得的最小内存大约为72M.抛出Spring Data REST,Spring Security和一些JPA实体,你将看到最低200M-300M.通过使用以下JVM选项,您可以获得总计约72M的简单Spring Boot应用程序.

With -XX:+UseSerialGC将与线程分配堆内存而不是专用GC线程内联执行垃圾收集

使用 -Xss512k这将限制每个线程堆栈内存为512KB而不是默认的1MB

使用 -XX:MaxRAM=72m这将限制JVM对堆和非堆管理内存的计算在此值的限制范围内.

除了上面的JVM选项,您还可以在application.properties文件中使用以下属性:

server.tomcat.max-threads=5 这会将HTTP请求处理程序线程的数量限制为1(默认值为50)


下面是docker stats运行具有上述限制和docker 参数的非常简单的Spring Boot应用程序的示例-m 72m.如果我将值降低到低于此值,则无法启动应用程序.

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)
Run Code Online (Sandbox Code Playgroud)

不要指望得到任何不错的性能,因为我想象GC会经常运行这个设置,因为它没有很多备用内存可供使用

  • @JeneralJames 这正是我在生产中发生的事情。我越来越觉得这不是容器化世界的技术。这确实是为单体应用程序服务器和数百个端点(控制器)而设计的。这就是为什么像 quarkus 这样的 Java 领域的新技术正在出现来解决这个问题。甚至更好的平台,如 Node/Go/.net core,都是为云/容器原生架构奠定基础的。 (6认同)
  • 2020 年的救星,使用“-XX:MaxRAM”设置让我的 Heroku dyno 不断抛出 R14 故障 (3认同)
  • 72MB?!哈!!是的,我的应用程序*启动*为 950 MB。Spring boot 2.3.0,无非就是几个REST控制器。启动时间不到 10 秒,但即使没有收到任何请求,没有施加任何负载,它也会飙升至 1GB 并保持在那里。 (3认同)

Hai*_* Li 11

搜索后,我发现它已经在stackoveflow中得到答案. Spring Boot内存消耗增加超出-Xmx选项

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.
Run Code Online (Sandbox Code Playgroud)

因为对于http服务(Tomcat或Undertow,Jetty),spring boot每个默认启动大约50个线程,并且每个线程使用1 MB(64位jvm默认设置).

因此在64位jvm中,内存使用量是堆(64M)+ Permgen(最大64M)+线程堆栈(1M x 50+)+本机句柄.

引用:

  • 这个接受的答案没有回答这个问题。问题是如何减少内存消耗,而不是解释为什么使用大量内存。 (2认同)
  • 了解事情发生的原因有助于解决问题。两个答案都很好,一个是细节,另一个是概述。他们互相称赞。 (2认同)