为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

翻阅古今 2021-06-20 18:10:55
我正在了解有关内存泄漏的更多信息,并尝试使用以下代码:我有下面的代码抛出 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 exceededimport 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());        }    }}问题:第一种情况的错误是否表示存在内存泄漏,而第二种情况则没有?
查看完整描述

2 回答

?
慕后森

TA贡献1802条经验 获得超5个赞

根据您的评论:

我正在尝试了解内存泄漏,所以我正在做的是打算......我正在寻找关于这两种情况的解释,以及第一种情况是否表示内存泄漏而第二种情况不

简单来说,两个错误都表明JVM内存不足,现在JVM是否因为内存泄漏而耗尽内存是另一回事。

现在,来到你的第一个案例 - 是的,存在内存泄漏(尽管是故意的),因为内部类持有封闭类的引用,因此使用创建的对象new LeakFactory()有资格进行 GC,但它们没有被 GC,因为Leak内部类持有他们。

要更清楚地看到这一点,请更改您的public class Leak{to public static class Leak{,您会注意到 JVM 将运行更长的时间,并且与您原来的非静态Leak内部类相比,OOM 将在几秒钟后出现。


查看完整回答
反对 回复 2021-06-23
?
HUX布斯

TA贡献1876条经验 获得超6个赞

内存泄漏是程序员无意中将内存保留的时间超过应有的时间的结果,这种无意的内存使用会慢慢累积,直到没有任何可分配的内存为止。

在 Java 中,考虑到垃圾收集的性质以及它实际上如何查看对象被引用的强度(或弱),泄漏内存很难做到。

鉴于您必须自己有意识地启动所有这些类,因此没有任何关于泄漏的争论;你是故意这样做的。您已经创建了足够多的引用,以至于耗尽了自己的内存限制。

Java 中的内存泄漏通常以比这更狡猾的方式表现出来;一些引用保存在一个finalize()方法中,该方法在类实际被垃圾收集之前不会被释放,并且只有 VM 知道实际发生的时间(它可能永远不会发生)。值得庆幸的是,该方法很快就会消失,因此使用方法看到泄漏的可能性至少会降低一点。

您也可能非常邪恶并Unsafe使用该语言做事,但这足以表明大多数明智的 IDE 和工具集会在您手上出现重大内存泄漏之前警告您这种用法。

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


查看完整回答
反对 回复 2021-06-23
  • 2 回答
  • 0 关注
  • 317 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信