Vil*_*oja 7 java spring spring-boot
我有一个 spring-boot 应用程序,我怀疑它可能存在内存泄漏。随着时间的推移,内存消耗似乎在增加,大约需要 500M 内存,直到我重新启动应用程序。重新启动后大约需要 150M。spring-boot 应用程序应该是一个非常无状态的休息应用程序,并且在请求完成后不应该留下任何对象。我希望垃圾收集器能够处理这个问题。
目前在生产中,spring-boot 应用程序似乎使用 343M 内存(RSS)。我获取了应用程序的堆转储并对其进行了分析。根据分析,heapdump的大小只有31M。那么缺失的300M到底在哪里呢?堆转储与应用程序使用的实际内存有何关联?我如何分析堆转储之后的内存消耗?如果使用的内存不在堆中,那么它在哪里呢?如何发现 spring-boot 应用程序的内存消耗情况?
除了堆之外,还有线程堆栈、元空间、JIT 代码缓存、本机共享库和堆外存储(直接分配)。
我将从线程堆栈开始:您的应用程序在峰值时产生多少个线程?默认情况下,每个线程可能为其堆栈分配 1MB,具体取决于 Java 版本、平台等。如果有 300 个活动线程(空闲或不空闲),您将分配 300MB 堆栈内存。
考虑将所有线程池设置为固定大小(或至少提供合理的上限)。即使这被证明不是您所观察到的问题的根本原因,它也会使应用程序的行为更具确定性,并帮助您更好地隔离问题。
那么缺失的300M到底在哪里呢?
对此进行了大量研究,特别是尝试调整控制非堆的参数。这项研究的成果之一是内存计算器(二进制)。
您会看到,在对可用内存量有硬性限制的 Docker 环境中,当 JVM 尝试分配比可用内存更多的内存时,它会崩溃。即使进行了所有研究,memory calculator
仍然有一个称为“head-room”的宽松选项 - 通常设置为总可用内存的 5% 到 10%,以防 JVM 决定无论如何获取更多内存(例如在密集垃圾收集期间)。
除了“head-room”之外,还memory calculator
需要 4 个额外的输入参数来计算控制内存使用的 Java 选项。
total-memory
- Spring Boot 应用程序至少 384 MB,从 512 MB 开始。loaded-class-count
- 最新的 Spring Boot 应用程序大约有 19000 个。这似乎随着每个 Spring 版本的增长而增长。请注意,这是最大值:设置太低的值将导致各种奇怪的行为(有时会抛出“OutOfMemory:非堆”异常,但并非总是如此)。thread-count
- 40 用于“正常使用”Spring Boot Web 应用程序。jvm-options
- 请参阅下面的两个参数。“算法”部分提到了可以调整的其他参数,我发现其中有两个值得针对每个应用程序进行研究并指定:
-Xss
设置为 256kb。除非您的应用程序具有非常深的堆栈(递归),否则将每个线程从 1 MB 增加到 256kb 可以节省大量内存。-XX:ReservedCodeCacheSize
设置为 64MB。“CodeCache”使用高峰通常出现在应用程序启动期间,从 192 MB 到 64 MB 可以节省大量可用作堆的内存。在运行时具有大量活动代码的应用程序(例如具有大量端点的Web应用程序)可能需要更多“CodeCache”。如果“CodeCache”太低,您的应用程序将使用大量CPU而不做太多事情(这也可以在启动过程中体现出来:如果“CodeCache”太低,您的应用程序可能需要很长时间才能启动)。“CodeCache”被 JVM 报告为非堆内存区域,应该不难测量。输出memory calculator
是一堆 Java 选项,它们都会影响 JVM 使用的内存。如果您确实想知道“丢失的 300M”在哪里,除了“Java Buildpack Memory Calculator v3”基本原理之外,还可以学习和研究这些选项中的每一个。
# Memory calculator 4.2.0
$ ./java-buildpack-memory-calculator --total-memory 512M --loaded-class-count 19000 --thread-count 40 --head-room 5 --jvm-options "-Xss256k -XX:ReservedCodeCacheSize=64M"
-XX:MaxDirectMemorySize=10M -XX:MaxMetaspaceSize=121289K -Xmx290768K
# Combined JVM options to keep your total application memory usage under 512 MB:
-Xss256k -XX:ReservedCodeCacheSize=64M -XX:MaxDirectMemorySize=10M -XX:MaxMetaspaceSize=121289K -Xmx290768K
Run Code Online (Sandbox Code Playgroud)
我们可以通过这种方式查看Spring Boot应用程序的内存消耗情况。
创建 spring boot 应用程序作为.jar
文件并使用执行它java -jar springboot-example.jar
现在打开 CMD 并输入jconsole
并按 Enter 键。
注意:- 在打开 jconsole 之前,您需要运行.jar
文件
选择 springboot-example.jar 并单击下面的连接按钮。
归档时间: |
|
查看次数: |
18575 次 |
最近记录: |