如何在Java8(SpringBoot)应用程序中设置最大非堆内存?
我有20个Spring Boot(2.3)嵌入式Tomcat应用程序,运行在8GB的Linux机器上。所有应用程序都是Java 1.8应用程序。机器内存不足,Linux开始杀死我的一些应用程序进程 使用Linux top和Spring Boot admin,我注意到最大内存堆设置为2GB:如何在Java8(SpringBoot)应用程序中设置最大非堆内存?,java,spring-boot,memory,Java,Spring Boot,Memory,我有20个Spring Boot(2.3)嵌入式Tomcat应用程序,运行在8GB的Linux机器上。所有应用程序都是Java 1.8应用程序。机器内存不足,Linux开始杀死我的一些应用程序进程 使用Linux top和Spring Boot admin,我注意到最大内存堆设置为2GB: java -XX:+PrintFlagsFinal -version | grep HeapSize 因此,20个应用程序中的每一个都试图获得2GB的堆大小(物理内存的1/4)。使用SpringBootAd
java -XX:+PrintFlagsFinal -version | grep HeapSize
因此,20个应用程序中的每一个都试图获得2GB的堆大小(物理内存的1/4)。使用SpringBootAdmin,我只能看到使用了~128MB。因此,我通过java-Xmx512m…
将最大堆大小减少到512,现在,Spring Boot admin显示:
1.33 GB分配给非堆空间,但仅使用121 MB。为什么要为非堆空间分配这么多?我怎样才能减少
更新
根据top,每个Java进程大约占用2.4GB(VIRT):
更新2
我为其中一个进程运行了jcmd 7505 VM.native_memory
,它报告:
7505:
Native Memory Tracking:
Total: reserved=1438547KB, committed=296227KB
- Java Heap (reserved=524288KB, committed=123808KB)
(mmap: reserved=524288KB, committed=123808KB)
- Class (reserved=596663KB, committed=83423KB)
(classes #15363)
(malloc=2743KB #21177)
(mmap: reserved=593920KB, committed=80680KB)
- Thread (reserved=33210KB, committed=33210KB)
(thread #32)
(stack: reserved=31868KB, committed=31868KB)
(malloc=102KB #157)
(arena=1240KB #62)
- Code (reserved=254424KB, committed=27120KB)
(malloc=4824KB #8265)
(mmap: reserved=249600KB, committed=22296KB)
- GC (reserved=1742KB, committed=446KB)
(malloc=30KB #305)
(mmap: reserved=1712KB, committed=416KB)
- Compiler (reserved=1315KB, committed=1315KB)
(malloc=60KB #277)
(arena=1255KB #9)
- Internal (reserved=2695KB, committed=2695KB)
(malloc=2663KB #19903)
(mmap: reserved=32KB, committed=32KB)
- Symbol (reserved=20245KB, committed=20245KB)
(malloc=16817KB #167011)
(arena=3428KB #1)
- Native Memory Tracking (reserved=3407KB, committed=3407KB)
(malloc=9KB #110)
(tracking overhead=3398KB)
- Arena Chunk (reserved=558KB, committed=558KB)
(malloc=558KB)
首先-否,未分配1.33GB。在屏幕截图上,您分配了127MB的非堆内存。1.33GB是最大限制 我看到您的元空间大约是80MB,这应该不会造成问题。剩下的记忆可以由很多东西组成。压缩类、代码缓存、本机缓冲区等 要获得消耗堆外内存的详细视图,可以查询MBean
java.lang:type=MemoryPool,name=*
,例如通过带有MBean插件的VisualVM
然而,你的应用程序可能只是消耗了太多的本地内存。例如,来自Netty的许多I/O缓冲区可能是罪魁祸首(被java.nio.DirectByteBuffer
使用)。如果这是罪魁祸首,您可以使用标记-Djdk.nio.maxCachedBufferSize
限制DirectByteBuffer
的缓存,或者使用-XX:MaxDirectMemorySize
设置限制。
为了确定到底是什么在消耗RAM,您必须创建一个堆转储并对其进行分析
所以,为了回答您的问题“为什么要将这么多的资源分配给非堆空间?我如何减少?”没有多少资源分配给非堆空间。其中大部分是用于I/O和JVM内部的本机缓冲区。没有通用开关或标志来同时限制所有不同的缓存和池
现在来回答房间里的大象。我认为你的真正的问题源于内存太少。您已经说过,您正在8GB机器上运行20个JVM实例,其堆空间限制为512MB。这是不可持续的。20 x 512MB=10GB堆,这超过了8GB总RAM的容量。而这还没有算在堆外/本机内存中。您需要提供更多的硬件资源,减少JVM计数,或者进一步减少堆/元空间和其他限制(我强烈建议不要这样做)。首先-不,1.33GB没有分配。在屏幕截图上,您分配了127MB的非堆内存。1.33GB是最大限制 我看到您的元空间大约是80MB,这应该不会造成问题。剩下的记忆可以由很多东西组成。压缩类、代码缓存、本机缓冲区等 要获得消耗堆外内存的详细视图,可以查询MBean
java.lang:type=MemoryPool,name=*
,例如通过带有MBean插件的VisualVM
然而,你的应用程序可能只是消耗了太多的本地内存。例如,来自Netty的许多I/O缓冲区可能是罪魁祸首(被java.nio.DirectByteBuffer
使用)。如果这是罪魁祸首,您可以使用标记-Djdk.nio.maxCachedBufferSize
限制DirectByteBuffer
的缓存,或者使用-XX:MaxDirectMemorySize
设置限制。
为了确定到底是什么在消耗RAM,您必须创建一个堆转储并对其进行分析
所以,为了回答您的问题“为什么要将这么多的资源分配给非堆空间?我如何减少?”没有多少资源分配给非堆空间。其中大部分是用于I/O和JVM内部的本机缓冲区。没有通用开关或标志来同时限制所有不同的缓存和池
现在来回答房间里的大象。我认为你的真正的问题源于内存太少。您已经说过,您正在8GB机器上运行20个JVM实例,其堆空间限制为512MB。这是不可持续的。20 x 512MB=10GB堆,这超过了8GB总RAM的容量。而这还没有算在堆外/本机内存中。您需要提供更多的硬件资源,减少JVM计数,或者进一步减少堆/元空间和其他限制(我强烈建议不要这样做)。除了已经说过的内容之外,这是一篇关于JVM中的元空间的非常好的文章,默认情况下,它保留了大约1GB的空间(尽管实际上可能没有使用那么多)。因此,如果您有许多小型应用程序,并且希望减少使用/保留的内存量,那么您可以使用标志
-XX:MaxMetaspaceSize
来调整这一点。除了已经说明的内容之外,这是一篇关于JVM中的元空间的非常好的文章,默认情况下,它保留了大约1GB的内存(尽管它实际上可能不会使用那么多)。因此,如果您有许多小型应用程序,并且希望减少已使用/保留的内存量,那么您可以使用标志-XX:MaxMetaspaceSize
调整这是另一件事。谢谢。这非常有帮助。不过,我仍然有一个疑问。根据top,我的每个Java进程的VIRT约为2.4GB。如果只有512 MB堆空间+127 MB非堆空间,我可以使用s已分配,那么为什么VIRT报告2.5GB?排名靠前的VIRT是虚拟内存,它包括所有代码、数据和共享库,加上已交换的页面和已映射但未使用的页面。因此,我敢打赌,这是很多东西的总和
7505:
Native Memory Tracking:
Total: reserved=1438547KB, committed=296227KB
- Java Heap (reserved=524288KB, committed=123808KB)
(mmap: reserved=524288KB, committed=123808KB)
- Class (reserved=596663KB, committed=83423KB)
(classes #15363)
(malloc=2743KB #21177)
(mmap: reserved=593920KB, committed=80680KB)
- Thread (reserved=33210KB, committed=33210KB)
(thread #32)
(stack: reserved=31868KB, committed=31868KB)
(malloc=102KB #157)
(arena=1240KB #62)
- Code (reserved=254424KB, committed=27120KB)
(malloc=4824KB #8265)
(mmap: reserved=249600KB, committed=22296KB)
- GC (reserved=1742KB, committed=446KB)
(malloc=30KB #305)
(mmap: reserved=1712KB, committed=416KB)
- Compiler (reserved=1315KB, committed=1315KB)
(malloc=60KB #277)
(arena=1255KB #9)
- Internal (reserved=2695KB, committed=2695KB)
(malloc=2663KB #19903)
(mmap: reserved=32KB, committed=32KB)
- Symbol (reserved=20245KB, committed=20245KB)
(malloc=16817KB #167011)
(arena=3428KB #1)
- Native Memory Tracking (reserved=3407KB, committed=3407KB)
(malloc=9KB #110)
(tracking overhead=3398KB)
- Arena Chunk (reserved=558KB, committed=558KB)
(malloc=558KB)