Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/324.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何分析spring启动应用程序内存消耗?_Java_Spring_Spring Boot - Fatal编程技术网

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

Java 如何分析spring启动应用程序内存消耗?,java,spring,spring-boot,Java,Spring,Spring Boot,我有一个spring boot应用程序,我怀疑它可能有内存泄漏。随着时间的推移,内存消耗似乎在增加,在我重新启动应用程序之前占用了大约5亿内存。重新启动后,大约需要150米。SpringBoot应用程序应该是一个非常无状态的rest应用程序,并且在请求完成后不应该留下任何对象。我希望垃圾收集器能处理好这件事 目前正在生产的SpringBoot应用程序似乎使用了343M内存(RSS)。我得到了应用程序的堆并对其进行了分析。根据分析,堆泵的尺寸只有31米。那么丢失的300米在哪里呢?heapdump

我有一个spring boot应用程序,我怀疑它可能有内存泄漏。随着时间的推移,内存消耗似乎在增加,在我重新启动应用程序之前占用了大约5亿内存。重新启动后,大约需要150米。SpringBoot应用程序应该是一个非常无状态的rest应用程序,并且在请求完成后不应该留下任何对象。我希望垃圾收集器能处理好这件事


目前正在生产的SpringBoot应用程序似乎使用了343M内存(RSS)。我得到了应用程序的堆并对其进行了分析。根据分析,堆泵的尺寸只有31米。那么丢失的300米在哪里呢?heapdump如何与应用程序正在使用的实际内存相关联?我如何通过heapdump分析内存消耗?如果使用的内存不在堆中,那么它在哪里?如何发现什么在消耗spring boot应用程序的内存?

除了堆,还有线程堆栈、元空间、JIT代码缓存、本机共享库和堆外存储(直接分配)

我将从线程堆栈开始:您的应用程序在峰值生成多少线程?默认情况下,每个线程可能会为其堆栈分配1MB,具体取决于Java版本、平台等。对于(比如)300个活动线程(空闲或不空闲),您将分配300MB的堆栈内存

考虑将所有线程池设置为固定大小(或者至少提供合理的上限)。即使这不是您观察到的问题的根本原因,它也会使应用程序的行为更具确定性,并将帮助您更好地隔离问题。

您可以使用“JProfiler” 远程或本地监视正在运行的java应用程序内存使用情况

那么丢失的300米在哪里呢

对此进行了大量的研究,特别是在试图调整控制非堆的参数方面。这项研究的一个结果是()

您可以看到,在对可用内存量有硬限制的Docker环境中,当JVM试图分配比可用内存更多的内存时,它会崩溃。即使进行了所有的研究,
内存计算器
仍然有一个称为“head-room”的松弛选项,通常设置为总可用内存的5%到10%,以防JVM决定获取更多内存(例如在密集的垃圾收集期间)

除了“head room”之外,
内存计算器
还需要4个额外的输入参数来计算控制内存使用的Java选项

  • 总内存
    -Spring Boot应用程序的最小内存为384 MB,从512 MB开始
  • 加载的类计数
    -对于最新的Spring Boot应用程序,大约为19000。这似乎随着每个Spring版本而增长。请注意,这是一个最大值:设置太低的值将导致各种奇怪的行为(有时会引发“OutOfMemory:non-heap”异常,但并不总是如此)
  • 线程数
    -40,用于“正常使用”Spring Boot web应用程序
  • jvm选项
    -请参阅下面的两个参数
“算法”部分提到了可以调整的其他参数,我发现其中两个参数值得对每个应用程序进行调查,并指定:

  • -Xss
    设置为256kb。除非您的应用程序有真正的深层堆栈(递归),否则每个线程从1MB到256kb会节省大量内存
  • -XX:ReservedCodeCacheSize
    设置为64MB。“CodeCache”的峰值使用通常在应用程序启动期间,从192MB到64MB可以节省大量内存,这些内存可以用作堆。运行时具有大量活动代码的应用程序(例如,具有大量端点的web应用程序)可能需要更多的“CodeCache”。如果“CodeCache”太低,您的应用程序将使用大量CPU而不会做太多事情(这也可能在启动期间表现出来:如果“CodeCache”太低,您的应用程序可能需要很长时间才能启动)。JVM将“CodeCache”报告为非堆内存区域,这应该不难测量
内存计算器的输出是一组Java选项,这些选项都会影响JVM使用的内存。如果您真的想知道“缺少的300M”在哪里,除了“JavaBuildPack内存计算器v3”之外,还可以研究这些选项

#内存计算器4.2.0
$./java buildpack内存计算器--总内存512M--加载类计数19000--线程计数40--主机室5--jvm选项“-XS256K-XX:ReservedCodeCacheSize=64M”
-XX:MaxDirectMemorySize=10M-XX:MaxMetaspaceSize=121289K-Xmx290768K
#组合的JVM选项可将应用程序内存总使用量保持在512 MB以下:
-Xss256k-XX:ReservedCodeCacheSize=64M-XX:MaxDirectMemorySize=10M-XX:MaxMetaspaceSize=121289K-Xmx290768K
如果您使用IntelliJ作为IDE来解决spring boot应用程序的内存相关问题,则可以将“yourkit”与IntelliJ一起使用。我以前使用过它,它为应用程序提供了更好的洞察力


关于内存配置的有趣文章:

我们可以通过这种方式查看spring boot应用程序中的内存消耗量

  • 将springboot应用程序创建为
    .jar
    文件,并使用
    java-jarspringboot example.jar

  • 现在打开CMD并键入jconsole,然后按enter键

    注意:-在打开jconsole之前,需要运行
    .jar
    文件

  • 现在您可以看到如下窗口,它将显示以前在本地进程部分运行的应用程序。

  • 选择springboot-example.jar并单击下面的连接按钮

  • 之后将显示以下提示并给出不安全连接选项。

  • 最后,您可以看到下面的概述(堆内存、线程…)。