“ java.lang.OutOfMemoryError:超出GC开销限制”是否表示内存泄漏?

时间:2018-08-01 22:26:00

标签: java

我正在学习有关内存泄漏的更多信息,并尝试使用以下代码:

我有下面的代码抛出Exception: java.lang.OutOfMemoryError thrown from the UncaughtExceptionHandler in thread "main"

import com.learn.general.memoryleaks.LeakFactory.Leak;

public class InnerClassMemoryLeakTest {
    static Leak[] leaks = new Leak[100000];

    public static void main(String[] args) {
        while(true) {
            for (int i = 0; i < leaks.length; i++) {
                leaks[i] = new LeakFactory().getLeak();
            }
        }
    }

    private static void createLeak() {
        while(true) {
            for (int i = 0; i < leaks.length; i++) {
                leaks[i] = new LeakFactory().getLeak();
            }
        }
    }
}


import java.util.Calendar;

public class LeakFactory {

    double d = Math.random();
    Calendar calendar = Calendar.getInstance();

    public Leak getLeak(){
        return new Leak();
    }

    public class Leak{
        double d_i = Math.random();
        Calendar calendar_i = Calendar.getInstance();
    }
}

然后我有下面的代码抛出Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded

import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

public class ArrayListMemoryLeak {

    public static void main(String[] args) {
        List<Object> calendars = new ArrayList<>();
        int count = 0;
        while(true){
            calendars.add(Calendar.getInstance());
        }
    }
}

问题:第一种情况下的错误是否表明存在内存泄漏,而第二种情况下的错误却没有?

3 个答案:

答案 0 :(得分:1)

内存泄漏是程序员无意中保持内存的时间超过了应有的时间,这种无意中的内存使用缓慢,直到没有可分配的内存为止。 >

在Java中,鉴于垃圾回收的性质以及如何看待引用对象的强弱程度,泄漏内存很难解决。

鉴于您必须自己故意 旋转所有这些类,因此没有任何理由要泄漏。您故意这样做。您已经创建了足够的引用,以致耗尽了自己的内存限制。

Java中的内存泄漏通常以一种更狡猾的方式表现出来;某些引用保留在finalize()方法中,直到类被实际垃圾回收时才释放,并且只有VM知道何时实际发生(永远不会)。 that method is going away Soon™值得庆幸的是,因此使用 that 看到泄漏的可能性至少有所降低。

您也可能不可思议邪恶并做Unsafe things with the language,但这足以构成危险信号,大多数明智的IDE和工具集都会在这种情况发生之前警告您这种用法。您的手上有大量内存泄漏。

所有这些要说的...不。您看到的异常表明您的内存不足。这不是直接表示内存泄漏。

答案 1 :(得分:0)

根据您的评论:

  

我正在尝试了解内存泄漏,因此我打算做什么   ....我正在寻找有关这两种情况以及是否首先   case表示内存泄漏而第二种情况不

简单地说,这两个错误都表明JVM内存不足,现在是否由于内存泄漏而导致JVM内存不足是另一回事。

现在,第一种情况-是的,内存泄漏(有意为之),因为内部类持有封闭类的引用,因此使用new LeakFactory()创建的对象可以使用GC,但不能进行GC因为Leak内部类对它们有很强的引用。

为更清楚地了解这一点,将public class Leak{更改为public static class Leak{,与原始的非静态{{1 }}内部类。

答案 2 :(得分:-1)

太多的对象失去了引用,因此被垃圾回收了。缺省情况下,JVM讨厌98%以上的程序处理专门用于丢弃对象(正在回收内存)。您可以重新调整对象的用途(通过使它们可变并直接将它们重新分配为新用途直接回收自己),也可以通过在命令行中添加-XX:-UseGCOverheadLimit来禁用构成错误的通知。当我自己做几次遗传算法时,我遇到了这个问题。在遗传算法中,很多父母从父母那里创建了许多孩子,然后在下一轮繁殖之前杀死了大多数最不适合的孩子。基本上,即使您实际上没有做错任何事情,您创建的垃圾也比Java所希望的更多。只需在命令行参数中添加-XX:-UseGCOverheadLimit即可查看它是否再次发生。要了解在使用eclipse时将其添加到何处,请遵循以下说明http://www.planetofbits.com/eclipse/increase-jvm-heap-size-in-eclipse/,但请将此行改为-XX:-UseGCOverheadLimit