如何分析spring启动应用程序的内存消耗?

hivapdat  于 2021-07-13  发布在  Java
关注(0)|答案(5)|浏览(407)

我有一个spring启动程序,我怀疑它可能有内存泄漏。随着时间的推移,内存消耗似乎在增加,在我重新启动应用程序之前占用了大约5亿内存。重新启动后大约需要150米。springboot应用程序应该是一个非常无状态的rest应用程序,并且在请求完成后不应该有任何对象遗留在周围。我希望垃圾收集者能处理好这件事。
目前正在生产的springboot应用程序似乎使用了343m的内存(rss)。我得到了应用程序的大量数据并进行了分析。根据分析,堆泵的尺寸只有31米。那么失踪的300米在哪里呢?heapdump如何与应用程序正在使用的实际内存相关联?我怎样才能分析内存消耗超过堆的情况呢?如果使用的内存不在堆中,那么它在哪里?如何发现是什么在消耗spring启动应用程序的内存?

pprl5pva

pprl5pva1#

除了堆,还有线程堆栈、元空间、jit代码缓存、本机共享库和堆外存储(直接分配)。
我将从线程堆栈开始:您的应用程序在峰值时生成多少个线程?默认情况下,每个线程可能会为其堆栈分配1mb,具体取决于java版本、平台等。对于(比如)300个活动线程(空闲或不空闲),您将分配300mb的堆栈内存。
考虑将所有线程池设置为固定大小(或者至少提供合理的上限)。即使这不是你观察到的问题的根本原因,它也会使应用程序的行为更具确定性,并帮助你更好地隔离问题。

oymdgrw7

oymdgrw72#

那么失踪的300米在哪里呢?
很多研究已经深入到这一点上,特别是在试图调整控制非堆的参数方面。这项研究的一个结果是内存计算器(二进制)。
您可以看到,在对可用内存量有硬限制的docker环境中,当jvm试图分配比可用内存更多的内存时,它会崩溃。即使进行了所有的研究 memory calculator 仍然有一个称为“head room”的slack选项—通常设置为总可用内存的5%到10%,以防jvm决定获取更多内存(例如在密集的垃圾收集期间)。
除了“头部空间”外 memory calculator 需要4个额外的输入参数来计算控制内存使用的java选项。 total-memory -spring boot应用程序的最小容量为384 mb,从512 mb开始。 loaded-class-count -最新的 Spring 启动应用程序约19 000。这似乎随着每个 Spring 版本而增长。请注意,这是一个最大值:设置太低的值将导致各种奇怪的行为(有时会引发“outofmemory:non-heap”异常,但并不总是如此)。 thread-count -对于“正常使用”的springbootweb应用程序为40。 jvm-options -请参见下面的两个参数。
“算法”部分提到了可以调整的其他参数,我发现每个应用程序有两个参数值得研究并指定: -Xss 设置为256kb。除非你的应用程序有很深的堆栈(递归),否则每个线程从1MB到256kb会节省很多内存。 -XX:ReservedCodeCacheSize 设置为64mb。“codecache”的使用高峰通常出现在应用程序启动期间,从192MB到64MB节省了大量可用作堆的内存。运行时具有大量活动代码的应用程序(例如,具有大量端点的web应用程序)可能需要更多的“codecache”。如果“codecache”太低,您的应用程序将使用大量的cpu而不会做太多的工作(这也可能在启动期间表现出来:如果“codecache”太低,您的应用程序可能需要很长时间才能启动)codecache”被jvm报告为非堆内存区域,应该不难测量。
输出 memory calculator 是一组java选项,它们都对jvm使用的内存有影响。如果您真的想知道“缺少的300m”在哪里,那么除了“javabuildpack内存计算器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
zaqlnxep

zaqlnxep3#

你可以用“jprofiler”https://www.ej-technologies.com/products/jprofiler/overview.html 远程或本地监视正在运行的java应用程序内存使用情况。

wljmcqd8

wljmcqd84#

如果您使用intellij作为ide来解决spring boot应用程序的内存相关问题,那么您可以将“yourkit”与intellij一起使用。我以前用过这个,它可以更好地洞察应用程序。
https://www.yourkit.com/docs/java/help/idea.jsp

yb3bgrhw

yb3bgrhw5#

关于内存分析的有趣文章:https://www.baeldung.com/java-profilers

相关问题