我遇到这样的问题,本地部署时抛出异常java.lang.OutOfMemoryError:GC overhead limit exceeded导致服务起不来,查看日志发现加载了太多资源到内存,本地的性能也不好,gc时间消耗的较多。解决这种问题两种方法是,增加参数,-XX:-UseGCOverheadLimit,关闭这个特性,同时增加heap大小,-Xmx1024m。坑填了,but why?

OOM大家都知道,就是JVM内存溢出了,那GC overhead limit exceed呢?

GC overhead limt exceed检查是Hotspot VM 1.6定义的一个策略,通过统计GC时间来预测是否要OOM了,提前抛出异常,防止OOM发生。Sun 官方对此的定义是:“并行/并发回收器在GC回收时间过长时会抛出OutOfMemroyError。过长的定义是,超过98%的时间用来做GC并且回收了不到2%的堆内存。用来避免内存过小造成应用不能正常工作。“

听起来没啥用...预测OOM有啥用?起初开来这玩意只能用来Catch住释放内存资源,避免应用挂掉。后来发现一般情况下这个策略不能拯救你的应用,但是可以在应用挂掉之前做最后的挣扎,比如数据保存或者保存现场(Heap Dump)。

而且有些时候这个策略还会带来问题,比如加载某个大的内存数据时频繁OOM。

假如你也生产环境中遇到了这个问题,在不知道原因时不要简单的猜测和规避。可以通过-verbose:gc -XX:+PrintGCDetails看下到底什么原因造成了异常。通常原因都是因为old区占用过多导致频繁Full GC,最终导致GC overhead limit exceed。如果gc log不够可以借助于JProfile等工具查看内存的占用,old区是否有内存泄露。分析内存泄露还有一个方法-XX:+HeapDumpOnOutOfMemoryError,这样OOM时会自动做Heap Dump,可以拿MAT来排查了。还要留意young区,如果有过多短暂对象分配,可能也会抛这个异常。

日志的信息不难理解,就是每次gc时打条日志,记录GC的类型,前后大小和时间。举个例子。

33.125: [GC [DefNew: 16000K->16000K(16192K), 0.0000574 secs][Tenured: 2973K->2704K(16384K), 0.1012650 secs] 18973K->2704K(32576K), 0.1015066 secs]

100.667:[Full GC [Tenured: 0K->210K(10240K), 0.0149142 secs] 4603K->210K(19456K), [Perm : 2999K->2999K(21248K)], 0.0150007 secs]

GC和Full GC代表gc的停顿类型,Full GC代表stop-the-world。箭头两边是gc前后的区空间大小,分别是young区、tenured区和perm区,括号里是该区的总大小。冒号前面是gc发生的时间,单位是秒,从jvm启动开始计算。DefNew代表Serial收集器,为Default New Generation的缩写,类似的还有PSYoungGen,代表Parallel Scavenge收集器。这样可以通过分析日志找到导致GC overhead limit exceeded的原因,通过调节相应的参数解决问题。

文中涉及到的名词解释,

Eden Space:堆内存池,大多数对象在这里分配内存空间。

Survivor Space:堆内存池,存储在Eden Space的gc中存活下来的对象。

Tenured Generation:堆内存池,存储Survivor Space中存活过几次gc的对象。

Permanent Generation:非堆空间,存储的是class和method对象。

Code Cache:非堆空间,JVM用来存储编译和存储native code。

最后附上GC overhead limit exceed HotSpot的实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
bool print_gc_overhead_limit_would_be_exceeded = false;
if (is_full_gc) {
  if (gc_cost() > gc_cost_limit &&
    free_in_old_gen < (size_t) mem_free_old_limit &&
    free_in_eden < (size_t) mem_free_eden_limit) {
    // Collections, on average, are taking too much time, and
    //      gc_cost() > gc_cost_limit
    // we have too little space available after a full gc.
    //      total_free_limit < mem_free_limit
    // where
    //   total_free_limit is the free space available in
    //     both generations
    //   total_mem is the total space available for allocation
    //     in both generations (survivor spaces are not included
    //     just as they are not included in eden_limit).
    //   mem_free_limit is a fraction of total_mem judged to be an
    //     acceptable amount that is still unused.
    // The heap can ask for the value of this variable when deciding
    // whether to thrown an OutOfMemory error.
    // Note that the gc time limit test only works for the collections
    // of the young gen + tenured gen and not for collections of the
    // permanent gen.  That is because the calculation of the space
    // freed by the collection is the free space in the young gen +
    // tenured gen.
    // At this point the GC overhead limit is being exceeded.
    inc_gc_overhead_limit_count();
    if (UseGCOverheadLimit) {
      if (gc_overhead_limit_count() >=
          AdaptiveSizePolicyGCTimeLimitThreshold){
        // All conditions have been met for throwing an out-of-memory
        set_gc_overhead_limit_exceeded(true);
        // Avoid consecutive OOM due to the gc time limit by resetting
        // the counter.
        reset_gc_overhead_limit_count();
      else {
        // The required consecutive collections which exceed the
        // GC time limit may or may not have been reached. We
        // are approaching that condition and so as not to
        // throw an out-of-memory before all SoftRef's have been
        // cleared, set _should_clear_all_soft_refs in CollectorPolicy.
        // The clearing will be done on the next GC.
        bool near_limit = gc_overhead_limit_near();
        if (near_limit) {
          collector_policy->set_should_clear_all_soft_refs(true);
          if (PrintGCDetails && Verbose) {
            gclog_or_tty->print_cr("  Nearing GC overhead limit, "
              "will be clearing all SoftReference");
          }
        }
      }
    }
    // Set this even when the overhead limit will not
    // cause an out-of-memory.  Diagnostic message indicating
    // that the overhead limit is being exceeded is sometimes
    // printed.
    print_gc_overhead_limit_would_be_exceeded = true;
 
  else {
    // Did not exceed overhead limits
    reset_gc_overhead_limit_count();
  }
}

参照&延伸阅读:

http://javaeesupportpatterns.blogspot.com/2012/01/gc-overhead-limit-exceeded-understand.html

http://www.oracle.com/technetwork/java/javase/gc-tuning-6-140523.html

http://reins.altervista.org/java/gc1.4.2_example.html

http://stackoverflow.com/questions/2129044/java-heap-terminology-young-old-and-permanent-generations

http://book.51cto.com/art/201306/399236.htm

https://blogs.oracle.com/jonthecollector/entry/presenting_the_permanent_generation

【OOM】GC overhead limit exceeded的更多相关文章

  1. 【jira】java.lang.OutOfMemoryError: GC overhead limit exceeded

    登录JIRA访问打开缓慢,查询日志出现下述提示:java.lang.OutOfMemoryError: GC overhead limit exceeded 修改setenv.sh文件中的JVM配置, ...

  2. Spark java.lang.outofmemoryerror gc overhead limit exceeded 与 spark OOM:java heap space 解决方法

    引用自:http://cache.baiducontent.com/c?m=9f65cb4a8c8507ed4fece7631046893b4c4380146d96864968d4e414c42246 ...

  3. Spark OOM:java heap space,OOM:GC overhead limit exceeded解决方法

    问题描述: 在使用spark过程中,有时会因为数据增大,而出现下面两种错误: java.lang.OutOfMemoryError: Java heap space java.lang.OutOfMe ...

  4. 记一次由于引用第三方服务导致的GC overhead limit exceeded异常

    最近笔者遇到一个问题  监控平台忽然告警 GC overhead limit exceeded 这个异常 第一反应估计是堆溢出了.于是各种各种jmap  jstack下载堆栈文件和堆日志文件. 以下是 ...

  5. java.lang.OutOfMemoryError:GC overhead limit exceeded填坑心得

    我遇到这样的问题,本地部署时抛出异常java.lang.OutOfMemoryError:GC overhead limit exceeded导致服务起不来,查看日志发现加载了太多资源到内存,本地的性 ...

  6. [转]java.lang.OutOfMemoryError:GC overhead limit exceeded

    我遇到这样的问题,本地部署时抛出异常java.lang.OutOfMemoryError:GC overhead limit exceeded导致服务起不来,查看日志发现加载了太多资源到内存,本地的性 ...

  7. GC overhead limit exceeded填坑心得

    我遇到这样的问题,本地部署时抛出异常java.lang.OutOfMemoryError:GC overhead limit exceeded导致服务起不来,查看日志发现加载了太多资源到内存,本地的性 ...

  8. eclipse:An internal error occurred during: "Build Project". GC overhead limit exceeded

    在使用Eclipse的Build Project功能时,提示以下错误: An internal error occurred during: "Build Project". GC ...

  9. 并发测试 java.lang.OutOfMemoryError: GC overhead limit exceeded Xms Xmx 阻塞请求 单节点 请求分发 负载均衡

    at javax.servlet.http.HttpServlet.service(HttpServlet.java:705) at javax.servlet.http.HttpServlet.se ...

随机推荐

  1. shell之 printf 输出语句

    总结: (1)printf 使用引用文本或空格分隔的参数,外面可以在printf中使用格式化字符串,还可以制定字符串的宽度.左右对齐方式等.默认printf不会像 echo 自动添加换行符,我们可以手 ...

  2. Ext.grid.EditorGridPanel分页刷新

    store.reload(); var start = grid.getBottomToolbar().cursor;//获取当前页开始条数 上面获取当前页第一条记录的方法有时候说未定义,我现在使用下 ...

  3. 多路复用(select、epoll)实现tcp服务

    -------------------------------多路复用的服务器(select)------------------------------- 网络通信被Unix系统抽象为文件的读写,通 ...

  4. 解决nginx FastCGI sent in stderr: “Primary script unknown”

    今天重启了mac,突然发现本地的 lnmp 服务不能用了,什么请求都返回了: FastCGI sent in stderr: "Primary script unknown" 这个 ...

  5. spring mvc:Error scanning entry module-info.class from jar错误

    项目从jdk1.6升级到jdk1.8,启动的时候出现如下错误: java.lang.RuntimeException: Error scanning entry module-info.class f ...

  6. 关于querySelector 和 document.getElementsByTagName 选中集合问题

    本文解决的问题是 :运用for..of..循环时,edge浏览器报Object doesn't support property or method 'symbol.iterator'问题 以及 符号 ...

  7. MPLS LDP随堂笔记1

    LDP 的使用原因(对于不同协议来说) LDP的四大功能 发现邻居 hello 5s 15s 224.0.0.2 发现邻居关系 R1 UDP 646端口 R2 UDP 646端口 此时形成邻居 建立邻 ...

  8. python--购物车优化

    基本要求:用户入口1.商品信息存在文件里 2.已购商品.余额记录,长期保存, 即第一次启动是需要输入预算的,以后就拿剩下的钱买东西 商家入口 1.可以添加商品,删除商品,修改商品价格 2.按q可以退出 ...

  9. Java 第五周总结

    1. 本周学习总结 2. 书面作业 1.代码阅读:Child压缩包内源代码 1.1 com.parent包中Child.java文件能否编译通过?哪句会出现错误?试改正该错误.并分析输出结果. 不能. ...

  10. 201521145048《Java程序设计》第5周学习总结

    1. 本章学习总结 2. 书面作业 Q1.代码阅读:Child压缩包内源代码 1.1 com.parent包中Child.java文件能否编译通过?哪句会出现错误?试改正该错误.并分析输出结果. 错误 ...