内部类导致的内存泄漏

文章探讨了Java中非静态内部类如何造成内存泄漏的问题。由于内部类对外部类有隐式引用,导致外部类无法被垃圾回收,从而占用内存。通过测试代码展示了这个问题,当循环创建大量包含内部类的对象时,最终引发内存溢出异常。解决方法是将内部类声明为静态,这样它将不再持有对外部类的引用,避免内存泄漏。

前两天刷文章偶然翻到一篇因使用非静态内部类时导致内存泄漏的问题,出于好奇自己也动手一试

什么叫内存泄漏

内存泄漏(Memory Leak)是指程序中已动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。

通俗点讲就是内存泄漏并不是指的物理上的内存遭到了泄漏,而是指代码中因为某些程序执行完之后没有释放所占用的空间所导致的,比如Java中我们new了一个对象,用完之后,因为某种原因这个对象没有被垃圾回收器回收,这就导致这个对象一直占用着这片空间久而久之导致服务崩溃.

非静态内部类导致内存泄漏的原因

之所以会发生这种类型的内存泄漏,是因为内部类的任何实例都包含对其外部类的隐式引用,且内部类始终能够访问其外部类-并非总是与JVM的计划一起使用。

测试代码

public class OutClass {

    private int[] i;

    public OutClass(int size) {
        this.i = new int[size];
    }

    public InClass test() {
        return new InClass();
    }

    public  class InClass{

    }
}
public class ClassTest {
    public static void main(String[] args) {
        List<OutClass.InClass> list = new ArrayList<>();
        int i = 1;
        while (true) {
            OutClass outClass = new OutClass(10000);
            list.add(outClass.test());
            System.out.println(i);
            i++;
        }
    }
}

编译之后

 我们可以看到多了一个OutClass$InClass.class的文件,拖进IDEA里反编译后有一个this$0的实例

 打断点启动程序

this$0的内存地址就是outClass的地址,也就是内部类持有外部类的实例,也就是上图OutClass$InClass对象

 放开端点继续执行

执行了84551次,程序就报出了内存溢出的异常

 解决此问题也容易,就是给内部类加上static关键字,使其变为静态内部类

反编译后没有了this$0实例

 打断点继续测试,此时内部类已经不在持有外部类的实例

  异常没有出现

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值