如何重现Java OutOfMemoryError - 超出GC开销限制 [英] How to reproduce Java OutOfMemoryError - GC overhead limit exceeded

查看:104
本文介绍了如何重现Java OutOfMemoryError - 超出GC开销限制的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  SecureRandom random =使用随机字符串填充它们,新的SecureRandom(); 
for(int i = 0; i <100000; i ++){
HashMap< String,String> map = new HashMap< String,String>(); (int j = 0; j <30; j ++){
map.put(new BigInteger(130,random).toString(32),new BigInteger(130,random).toString( 32));




$ b我已经提供了-XX:+ UseGCOverheadLimit jvm参数,但不能得到错误。是否有任何简单可靠的方法/黑客得到这个错误? 假设他们都没有为你工作。这是一个会的。但首先,审查条件触发此错误


如果在垃圾收集中花费了太多时间,并行收集器将抛出一个OutOfMemoryError:if more超过总时间的98%花在垃圾回收上,并且只有不到2%的堆被回收了。

所以,你必须消耗几乎所有的堆,保持它分配,然后分配大量的垃圾。把很多东西放到 Map 中不会为你做这件事。

  public static void main(String [] argv)
throws Exception
{
List< Object> fixedData = consumeAvailableMemory();
while(true)
{
Object data = new byte [64 * 1024 - 1];
}
}


private static List< Object> consumeAvailableMemory()
抛出异常
{
LinkedList< Object> holder = new LinkedList< Object>();
while(true)
{
try
{
holder.add(new byte [128 * 1024]);
}
catch(OutOfMemoryError ex)
{
holder.removeLast();
回报持有者;



code
$ b consumeAvailableMemory()方法用相对较小的内存块填充堆。 相对较小是非常重要的,因为JVM会将大对象(我的经验为512k字节)直接放入终身代,让年轻一代空着。

After我消耗了大部分堆,我只是分配和丢弃。这个阶段较小的块大小非常重要:我知道我将有足够的内存用于至少一次分配,但可能不会超过两次。这会使GC保持活动状态。



运行这个命令会在一秒钟内产生所需的错误:

 > java -Xms1024m -Xmx1024m GCOverheadTrigger 
线程main中的异常java.lang.OutOfMemoryError:在GCOverheadTrigger.main(GCOverheadTrigger.java:12)
的GC开销限制为了完整起见,我使用了JVM:

 > java -version 
java版本1.6.0_45
Java™SE运行时环境(build 1.6.0_45-b06)
Java HotSpot™64位服务器虚拟机(版本20.45 -b01,混合模式)

现在我的问题是你为什么要在世界上想要做这个?


My approach was to create hundred thousand local collections and populate them with random strings, something like this:

    SecureRandom random = new SecureRandom();
    for(int i = 0 ; i < 100000 ; i++){
        HashMap<String, String> map = new HashMap<String, String>();
        for(int j = 0 ; j < 30 ; j++){
            map.put(new BigInteger(130, random).toString(32), new BigInteger(130, random).toString(32));
        }
    }

I have provided -XX:+UseGCOverheadLimit jvm parameter too, but can not get the error. Is there any easy and reliable way/hack to get this error?

解决方案

Since you haven't accepted any answer, I'll assume that none of them have worked for you. Here's one that will. But first, a review of the conditions that trigger this error:

The parallel collector will throw an OutOfMemoryError if too much time is being spent in garbage collection: if more than 98% of the total time is spent in garbage collection and less than 2% of the heap is recovered

So, you have to consume almost all of the heap, keep it allocated, and then allocate lots of garbage. Putting lots of stuff into a Map isn't going to do this for you.

public static void main(String[] argv)
throws Exception
{
    List<Object> fixedData = consumeAvailableMemory();
    while (true)
    {
        Object data = new byte[64 * 1024 - 1];
    }
}


private static List<Object> consumeAvailableMemory()
throws Exception
{
    LinkedList<Object> holder = new LinkedList<Object>();
    while (true)
    {
        try
        {
            holder.add(new byte[128 * 1024]);
        }
        catch (OutOfMemoryError ex)
        {
            holder.removeLast();
            return holder;
        }
    }
}

The consumeAvailableMemory() method fills up the heap with relatively small chunks of memory. "Relatively small" is important because the JVM will put "large" objects (512k bytes in my experience) directly into the tenured generation, leaving the young generation empty.

After I've consumed most of the heap, I just allocate and discard. The smaller block size in this phase is important: I know that I'll have enough memory for at least one allocation, but probably not more than two. This will keep the GC active.

Running this produces the desired error in under a second:

> java -Xms1024m -Xmx1024m GCOverheadTrigger
Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded
    at GCOverheadTrigger.main(GCOverheadTrigger.java:12)

And, for completeness, here's the JVM that I'm using:

> java -version
java version "1.6.0_45"
Java(TM) SE Runtime Environment (build 1.6.0_45-b06)
Java HotSpot(TM) 64-Bit Server VM (build 20.45-b01, mixed mode)

And now my question for you: why in the world would you want to do this?

这篇关于如何重现Java OutOfMemoryError - 超出GC开销限制的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆