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

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


我有下面的代码抛出 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());

        }

    }

}

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


翻阅古今
浏览 318回答 2
2回答

慕后森

根据您的评论:我正在尝试了解内存泄漏,所以我正在做的是打算......我正在寻找关于这两种情况的解释,以及第一种情况是否表示内存泄漏而第二种情况不简单来说,两个错误都表明JVM内存不足,现在JVM是否因为内存泄漏而耗尽内存是另一回事。现在,来到你的第一个案例 - 是的,存在内存泄漏(尽管是故意的),因为内部类持有封闭类的引用,因此使用创建的对象new LeakFactory()有资格进行 GC,但它们没有被 GC,因为Leak内部类持有他们。要更清楚地看到这一点,请更改您的public class Leak{to&nbsp;public static class Leak{,您会注意到 JVM 将运行更长的时间,并且与您原来的非静态Leak内部类相比,OOM 将在几秒钟后出现。

HUX布斯

内存泄漏是程序员无意中将内存保留的时间超过应有的时间的结果,这种无意的内存使用会慢慢累积,直到没有任何可分配的内存为止。在 Java 中,考虑到垃圾收集的性质以及它实际上如何查看对象被引用的强度(或弱),泄漏内存很难做到。鉴于您必须自己有意识地启动所有这些类,因此没有任何关于泄漏的争论;你是故意这样做的。您已经创建了足够多的引用,以至于耗尽了自己的内存限制。Java 中的内存泄漏通常以比这更狡猾的方式表现出来;一些引用保存在一个finalize()方法中,该方法在类实际被垃圾收集之前不会被释放,并且只有 VM 知道实际发生的时间(它可能永远不会发生)。值得庆幸的是,该方法很快就会消失,因此使用该方法看到泄漏的可能性至少会降低一点。您也可能非常邪恶并Unsafe使用该语言做事,但这足以表明大多数明智的 IDE 和工具集会在您手上出现重大内存泄漏之前警告您这种用法。所有这些都是为了说......不。您看到的异常表明您的内存不足。它并不直接表示内存泄漏。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java