【问题标题】:Garbage collection acting weird垃圾收集行为怪异
【发布时间】:2018-01-29 10:36:55
【问题描述】:

我刚接触一个项目,他们要求我调查为什么服务器(应用程序)表现得很奇怪。重新启动后,它们的速度非常快(

内存和 CPU 会上升,并且在应用程序重新启动之前不会下降。

因此,他们正在运行具有以下命令行标志的 Tomcat (hybris) 服务器: -XX:ConcGCThreads=1 -XX:G1HeapRegionSize=4194304 -XX:GCLogFileSize=786432 -XX:InitialHeapSize=12884901888 -XX:+ManagementServer -XX:MaxGCPauseMillis=200 -XX:MaxHeapSize=12884901888 -XX:NewRatio=4 -XX: NumberOfGCLogFiles=10 -XX:-OmitStackTraceInFastThrow -XX:ParallelGCThreads=4 -XX:+ParallelRefProcEnabled -XX:+PrintGC -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -XX:+PrintTenuringDistribution -XX:ReservedCodeCacheSize=134217728 -XX:ThreadStackSize= 1024 -XX:+UseCodeCacheFlushing -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseG1GC -XX:+UseGCLogFileRotation -XX:+UseTLAB

在下图中,您可以看到重启前后的 CPU 和内存使用情况。应用服务器已经承受了几个小时的高负载...

CPU & Memory usage

Heap & Eden Heap Usage

Old Gen Heap Usage

Garbage Collection CPU time

应用服务器本身是一个 4 核的 16GB RAM。

两次重启之间完整运行的屏幕截图:

【问题讨论】:

  • 您是否曾在代码中使对象无效?您是否只是继续创建对象而不删除旧对象? ...
  • 不,我们不会继续创建对象。但是,我们确实在缓存中保留了很多产品和变体。
  • 而且可能在内存压力的时候缓存没有释放对象。因此内存泄漏。 (这是一种可能性....)
  • 根据图表,您有一个 ~12GB 的已提交堆,并且已使用的堆甚至没有触及 10GB 线,所以我没有看到任何与垃圾收集相关的问题。实际的问题应该是为什么系统在重负载时间开始交换,而当使用的物理内存仍然报告为 ~85% 时。但这不是 Java 问题……

标签: java performance memory garbage-collection hybris


【解决方案1】:

您的应用程序有内存泄漏。

这不是垃圾收集器 (GC) 问题,而是您的应用程序中的错误。这意味着某些对象已创建,但未使用 GC 清理,因为指向它们的引用链接仍然存在于您的应用程序中。您应该调查哪些对象没有被清理并追踪它们是如何创建的以及引用离开的位置。

正如您提到的 TomCat,我将首先检查 Servlet(或如果您使用 Spring,则为控制器和服务)的类属性变量。

【讨论】:

  • 查找内存泄漏的方法是使用内存配置文件和一些堆快照来了解哪些对象正在消耗内存。然后向后工作....
  • 对。这是正确的方法,尽管我个人发现如果我知道我在寻找什么并且应用程序具有清晰的结构,很容易找到错误的代码。如果不是这种情况,那么你是对的 - 堆快照和相关的东西。我个人为此使用 Oracle VisualVM 工具。
  • @Pavlo 您如何计算内存泄漏?虽然 heap & eden 图可能显示出内存泄漏的趋势,但不确定。但是,这些图表仅涵盖 4 小时:s,这还不够。
  • 如果不是内存泄漏会是什么?
  • @Erik 我将添加一个从应用程序启动到重新启动的图表
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-21
相关资源
最近更新 更多