zoukankan      html  css  js  c++  java
  • Out of memory error : GC overhead limit exceeded

    GC overhead limit exceeded 是指垃圾回收器通过分析当前内存使用趋势,提前抛出异常而不是真正等到内存耗尽再抛出异常。如果真正等到内存耗尽再抛出异常,可能的后果是:我们连保存重要数据的空间都没了。

    那么GC是如何分析内存使用趋势来决定是否跑出此异常呢? 默认情况下, 如果内存使用量达到一个阈值之后,GC花费的时间超过 98%, 并且GC回收的内存少于 2%,JVM就会抛出异常。也就是说,GC发现“内存将尽,大厦将倾”,而自己“鞠躬尽瘁”,“费力不讨好”,总做“无用功”的时候,GC就会抛出异常。

    明白了异常发生的原理,我们很容易“制造”异常来模拟“车祸”现场。下面的代码随机生成字符串,并把字符串添加到列表。因为这些新创建的字符串无法被GC回收,在内存溢出之前,GC就率先抛出异常了。

    运行这段程序使用-Xmx12m参数,把堆设的小一些效果更明显。

    package wyf.clonesite;
    
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Random;
    
    public class BugShooter {
    String randomString() {
        StringBuilder builder = new StringBuilder();
        Random r = new Random();
        for (int i = 0; i < 30; i++) {
            builder.append(r.nextInt(100));
        }
        return builder.toString();
    }
    
    BugShooter() {
        int cnt = 0;
        try {
            List<String> a = new ArrayList<>();
            while (true) {
                cnt++;
                a.add(randomString());
                if (cnt % 1000 == 0) System.out.println(cnt);
            }
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println(cnt);
        }
    }
    
    public static void main(String[] args) {
        new BugShooter();
    }
    }
    
    

    异常内容如下:

    Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded
    	at java.util.Random.<init>(Random.java:137)
    	at java.util.Random.<init>(Random.java:105)
    	at wyf.clonesite.BugShooter.randomString(BugShooter.java:10)
    	at wyf.clonesite.BugShooter.<init>(BugShooter.java:23)
    	at wyf.clonesite.BugShooter.main(BugShooter.java:33)
    

    GC提前抛出异常看的是内存使用的“速度”,而内存溢出看的是内存使用的“路程”。速度如果太快,GC就认为很危险。

    实际中,我们可能确实会有大量开辟不可回收对象的场景,那么如何解决这个问题呢?

    • 下策:关闭GC提前抛出异常的机制,使用-XX:-UseGCOverheadLimit
    • 中策:捕捉此异常,在内存耗尽之前dump程序状态,备份好数据,坦然“就义”
    • 上策:加大堆空间-Xmx1024m

    参考资料

    https://blog.csdn.net/renfufei/article/details/77585294
    https://blog.csdn.net/evilcry2012/article/details/79063822

  • 相关阅读:
    HYSBZ 2818 gcd
    hdu1695 GCD
    HYSBZ 2301
    poj 2096
    正则表达式匹配HTML标签或标记
    [转载]Sed 命令详解 正则表达式元字符
    [转载]Shell删除各种注释的脚本
    [转载]sed实现直接修改文件内容
    [转载]强大的grep用法详解:grep与正则表达式
    [转载]【Shell脚本】逐行处理文本文件
  • 原文地址:https://www.cnblogs.com/weiyinfu/p/9815410.html
Copyright © 2011-2022 走看看