【问题标题】:Java Garbage Collector Allocation FailureJava 垃圾收集器分配失败
【发布时间】:2016-02-27 05:57:57
【问题描述】:

我在具有 8GB 内存和 4 个 CPU 的机器上运行我的 java 应用程序。 但是在通过压力测试运行应用程序较长时间后,观察到垃圾收集器问题,因为内存已完全满,并且似乎 gc 周期需要更长的时间才能完成,但我无法找出可能的原因及其解决方案。 我们完成请求的平均延迟没有太大差异。但是它不能同时服务很多线程。

我已经使用以下参数启动了我的应用程序

-Xms4096M -Xmx4096M 
-XX:MaxPermSize=512M 
-XX:PermSize=512m 
-XX:+UseConcMarkSweepGC 
-XX:+HeapDumpOnOutOfMemoryError 
-XX:+PrintGCTimeStamps 
-XX:+PrintGCDetails 
-XX:+PrintGCApplicationStoppedTime 
-XX:+PrintGCApplicationConcurrentTime 
-XX:+PrintHeapAtGC 
-Xloggc:/root/tomcat_logs/gc_logs.log

top 命令的输出

top - 11:24:03 up 44 days, 23:45,  1 user,  load average: 0.39, 0.47, 0.65
Tasks: 158 total,   1 running, 157 sleeping,   0 stopped,   0 zombie
Cpu(s): 18.8%us,  2.1%sy,  0.0%ni, 64.2%id, 12.9%wa,  0.2%hi,  1.8%si,  0.0%st
Mem:   7672012k total,  7270396k used,   401616k free,   238468k buffers
Swap:  5238776k total,    34584k used,  5204192k free,  2390820k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND                                                                           
15811 root      20   0 7919m 4.1g   9m S 101.1 55.9   4134:37 java 

填充内存后的示例 GC 日志

{Heap before GC invocations=193901 (full 4):
 par new generation   total 306688K, used 274312K [0x00000006c0000000, 0x00000006d4cc0000, 0x00000006d4cc0000)
  eden space 272640K, 100% used [0x00000006c0000000, 0x00000006d0a40000, 0x00000006d0a40000)
  from space 34048K,   4% used [0x00000006d2b80000, 0x00000006d2d222c8, 0x00000006d4cc0000)
  to   space 34048K,   0% used [0x00000006d0a40000, 0x00000006d0a40000, 0x00000006d2b80000)
 concurrent mark-sweep generation total 3853568K, used 687930K [0x00000006d4cc0000, 0x00000007c0000000, 0x00000007c0000000)
 Metaspace       used 58528K, capacity 59902K, committed 61732K, reserved 1103872K
  class space    used 6866K, capacity 7109K, committed 7464K, reserved 1048576K
89974.407: [GC (Allocation Failure) 89974.407: [ParNew: 274312K->1655K(306688K), 0.0101861 secs] 962243K->689622K(4160256K), 0.0104010 secs] [Times: user=0.04 sys=0.00, real=0.01 secs] 
Heap after GC invocations=193902 (full 4):
 par new generation   total 306688K, used 1655K [0x00000006c0000000, 0x00000006d4cc0000, 0x00000006d4cc0000)
  eden space 272640K,   0% used [0x00000006c0000000, 0x00000006c0000000, 0x00000006d0a40000)
  from space 34048K,   4% used [0x00000006d0a40000, 0x00000006d0bdded0, 0x00000006d2b80000)
  to   space 34048K,   0% used [0x00000006d2b80000, 0x00000006d2b80000, 0x00000006d4cc0000)
 concurrent mark-sweep generation total 3853568K, used 687966K [0x00000006d4cc0000, 0x00000007c0000000, 0x00000007c0000000)
 Metaspace       used 58528K, capacity 59902K, committed 61732K, reserved 1103872K
  class space    used 6866K, capacity 7109K, committed 7464K, reserved 1048576K
}
89974.418: Total time for which application threads were stopped: 0.0127352 seconds
89974.988: Application time: 0.5703336 seconds

我想得出结论,为什么内存这么多,以及我可以做些什么来克服它,以便我可以在更高负载的情况下长期运行我的应用程序。请帮我这样做。

【问题讨论】:

  • 您还可以为初始堆大小和最大堆大小设置不同的值。这样,GC 将定期扫描取消引用的对象,并且您的 GC 周期会很短。还要配置你的 jconsole 来检查内存泄漏!

标签: java spring garbage-collection jvm concurrent-mark-sweep


【解决方案1】:

基本上你面临着可能的内存泄漏。使用 YourKIt(或您选择的分析器),运行您的应用程序,并在适当的时候,定期强制垃圾收集,然后检查尽管强制 gc 哪些对象仍在累积。这可能是一项耗时的活动,但最终会得到回报。

可能的原因可能是 ClassLoader 泄漏、弱引用、缓存实现不当或其他任何原因。

【讨论】:

    【解决方案2】:

    从您提供的日志摘录中看不出问题。

    [Times: user=0.04 sys=0.00, real=0.01 secs]

    收集耗时 10 毫秒。

    并发标记-扫描生成总数 3853568K,已使用 687966K [0x00000006d4cc0000, 0x00000007c0000000, 0x00000007c0000000)

    老年代只有 680MB/3.8G 满。

    虽然这只是一个年轻一代的集合,所以也许你已经发布了你日志中不相关的部分。也许是因为你认为“失败”意味着“坏”?不是这种情况。它只是年轻代收集的触发器,这意味着如果不先收集年轻代,就无法满足分配。

    您可能希望通过 GCViewer 运行整个过程,看看您是否真的遇到了 GC 问题。

    【讨论】:

      猜你喜欢
      • 2019-02-01
      • 2011-11-07
      • 1970-01-01
      • 1970-01-01
      • 2018-01-08
      • 2010-12-13
      • 2011-01-06
      • 2013-10-22
      • 2012-04-08
      相关资源
      最近更新 更多