【问题标题】:Tomcat memory growingTomcat内存增长
【发布时间】:2018-07-22 15:02:47
【问题描述】:

是什么导致tomcat内存增长和下降

【问题讨论】:

  • 由于内存清空成功,这是正常的。 Tomcat 显然有在后台运行的周期性任务,这些任务创建对象并因此分配内存。您可以做的是通过 VisualVM 或其他分析器工具监视应用程序,以确定定期创建的对象或查看源代码。
  • 你用的是哪个版本的jvm和tomcat?您是否尝试过全新的 tomcat 安装?
  • @MehmetSunkur 尝试使用 Java 7 和 tomcat 5.5 以及 java 8 和 tomcat 8.5
  • 这是一个有趣的问题。显然这不是内存泄漏(因为内存通过 GC 返回)。正如你所说的“如果我要给 JVM 更多的内存,比如 12gb,那么 zig zag 模式会从 500mb 变为 3GB”,我想这是因为 GC 是礼貌的,如果不需要,它不想打扰 JVM。但是tomcat在空闲时间做什么会很高兴知道。您是否尝试将您的问题转发给 tomcat 团队?

标签: java apache tomcat


【解决方案1】:

让我们看看图表 大约在 12:08,工作内存的大小达到最大值 (199 MB)。

大约在 12:09,垃圾收集器开始工作,死对象被收集,工作内存大小约为 145 MB。

12:12 左右,工作内存增加,产生了很多死对象,内存从 145 MB --> 155 MB --> 165 MB --> 180 MB --> ... --> 190 MB .

大约12:13,垃圾收集器再次工作,死物被收集,工作内存大小约为145 MB。

...等等。 实际上,如果没有特殊事件发生,它是一个周期图。

【讨论】:

  • 您可以在javaworld.com/article/2073905/build-ci-sdlc/… 阅读更多内容,参见图 7
  • 知道是什么导致内存在不使用应用程序的情况下增长吗?是jvm还是tomcat?
  • 当我没有运行任何 Web 应用程序时,我检查了 Apache Tomcat。它仍然增加,然后减少,然后增加内存......垃圾收集器循环正在工作。 Tomcat只是Java应用的一个例子,你可以使用其他Java应用。
【解决方案2】:

以下是了解链接答案中解释的锯齿形模式的要点:

  • 当收集器运行时,它首先尝试部分收集,仅释放最近分配的内存
  • 最近创建的仍处于活动状态的对象得到“提升”
  • 一旦一个对象被提升了几次,即使它已经准备好收集,它也不会再被部分收集清理
  • 这些对象称为tenured,只有在需要完整收集以便为程序继续运行腾出足够空间时才会清理

问题:是什么导致即使应用程序完全空闲,内存也会如此增长?

答案: 有内部计划作业,如 自动化计时器 等,或一些外部进程监控导致内存增长该应用程序处于空闲状态。也许您的应用程序具有相同数量的对象,但有些可能更大。例如,您可能有一些 ArryList 和一些 StrigBuilder 会不断增长缓存。

来源:

【讨论】:

  • 首先是什么导致内存增长,你知道吗?
【解决方案3】:

http://www.oracle.com/technetwork/java/gc-tuning-5-138395.html 首先,这里有一个有用的链接“使用 5.0 Java TM 虚拟机调整垃圾收集”

这听起来确实像 GC 暂停使 tomcat 无响应。一开始是使用选项 -XX:+UseConcMarkSweepGC 的“低暂停”垃圾收集器。

【讨论】:

    【解决方案4】:

    原因可能多种多样,没有关于您的应用程序的更多信息:假设它自己没有执行任何重复性任务,一个可能的原因可能是 JConsole 本身,因为收集信息并通过 RMI 发送它会消耗内存,这可能会很快从伊甸空间收集。

    您可以通过使用较少“侵入性” 的工具(例如使用-verbosegc 启用 GC 详细输出)并比较类似设置中的内存使用情况来测试此假设。

    正如其他答案中强调的那样,Tomcat 也可以有自己的开销。您可以通过提供 "hello, world" servlet 并使用类似工具比较两者的内存消耗来测试其他假设。

    【讨论】:

      【解决方案5】:

      导致锯齿形图案的是 jconsole 本身。

      要查看jconsolejvisualvm 的效果,您可以编写一个只有一个主循环的简单java 程序。例如

      public static void main(String[] args) {
          while (true) {
              try {
                  Thread.sleep(500);
              } catch (InterruptedException e) {
              }
          }
      }
      

      只用一点点java -Xmx20m ... 执行它。这将帮助您更好地查看堆利用率,因为我接下来将使用的工具 jstat 以百分比形式打印利用率。

      现在打开一个命令行窗口并执行jstat。您将需要 java 进程的 PID,可以使用 jps -l 找到它。

      jstat -gcutil <PID>
      

      它会打印出这样的东西

        S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT
        0,00   0,00  69,34   0,00  14,48  17,19      0    0,000     0    0,000    0,000
      

      关注伊甸园空间E。该值是空间当前容量的百分比。详情请查看jstat

      如果您一次又一次地执行该命令,您将看到伊甸园空间利用率不会增长。它保持在例如69,34。我在我的 Windows 上使用类似 linux watch 的命令以特定时间间隔重新运行该命令。见watch.bat

      现在打开jconsole

      jconsole <PID>
      

      并一次又一次地执行jstat 命令。您会看到伊甸园空间不断增长,直到达到最大值并被垃圾回收。

      这是jstat --gcutil &lt;PID&gt; 的输出,间隔为 1 秒。关注伊甸空间E

        S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT
        0,00   0,00  67,42   0,00  14,48  17,19      0    0,000     0    0,000    0,000
        S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT
        0,00   0,00  67,42   0,00  14,48  17,19      0    0,000     0    0,000    0,000
      # jconsole connected
        S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT
        0,00  96,88  81,64   7,57  92,26  84,87      1    0,001     0    0,000    0,001
        S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT
        0,00  96,88  84,66   7,57  92,26  84,87      1    0,001     0    0,000    0,001
        S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT
        0,00  96,88  89,70   7,57  92,26  84,87      1    0,001     0    0,000    0,001
        S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT
        0,00  96,88  91,70   7,57  92,26  84,87      1    0,001     0    0,000    0,001
        S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT
        0,00  96,88  93,70   7,57  92,26  84,87      1    0,001     0    0,000    0,001
        S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT
        0,00  96,88  95,70   7,57  92,26  84,87      1    0,001     0    0,000    0,001
        S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT
        0,00  96,88  96,70   7,57  92,26  84,87      1    0,001     0    0,000    0,001
        S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT
        0,00  96,88  98,71   7,57  92,26  84,87      1    0,001     0    0,000    0,001
      # Garbage collected
        S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT
      100,00   0,00   1,13  14,06  94,75  89,26      2    0,003     0    0,000    0,003
        S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT
      100,00   0,00   3,00  14,06  94,75  89,26      2    0,003     0    0,000    0,003
        S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT
      100,00   0,00   5,75  14,06  94,75  89,26      2    0,003     0    0,000    0,003
      

      如您所见... 在 jconsole 连接到进程后,伊甸园空间不断增长,直到它被垃圾收集。这会导致锯齿形图案。这是来自jvisualvm 的快照。

      当您对您的 tomcat 进程执行相同操作时,您会发现类似的行为。唯一的区别是即使没有连接 jconsole,伊甸园空间也会略微增长。但是这种轻微的增长并不是你看到的之字形图案的原因。

      这是我的 tomcat 的 jstat 输出。

        S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT
        0,00  99,80  70,33   4,81  96,85  90,10      5    0,037     0    0,000    0,037
        S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT
        0,00  99,80  70,33   4,81  96,85  90,10      5    0,037     0    0,000    0,037
        S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT
        0,00  99,80  70,43   4,81  96,85  90,10      5    0,037     0    0,000    0,037
        S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT
        0,00  99,80  70,43   4,81  96,85  90,10      5    0,037     0    0,000    0,037
        S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT
        0,00  99,80  70,43   4,81  96,85  90,10      5    0,037     0    0,000    0,037
        S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT
      

      此输出持续 36 秒,直到您可以看到内存的微小变化。从70,4370,53

        S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT
        0,00  99,80  70,43   4,81  96,85  90,10      5    0,037     0    0,000    0,037
        S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT
        0,00  99,80  70,53   4,81  96,85  90,10      5    0,037     0    0,000    0,037
        S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT
        0,00  99,80  70,53   4,81  96,85  90,10      5    0,037     0    0,000    0,037
      

      因此这个小改动是tomcat的后台进程唯一负责的事情。

      PS:您也可以不时使用Memory Analyser 并获取堆转储,您将看到byte[] 数组的已用内存量增加,因为RMI 网络流量。

      【讨论】:

      • 感谢您的回答。这不是让我奖励你全部 500 我猜是因为赏金时间已经结束。我认为它不会有所不同
      猜你喜欢
      • 2014-12-27
      • 1970-01-01
      • 1970-01-01
      • 2014-12-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-23
      相关资源
      最近更新 更多