欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

thread导致的内存泄漏实例——为什么使用静态内部类避免内存泄漏

程序员文章站 2022-03-02 14:36:01
...

背景:有个数据库处理类,包含一个thread负责对数据库进行写入(耗时操作)。该thread在某个fragment中会被重新初始化并开始。

 

        private void updateBookShelf() {
            Globals.getInstance().setBookShelves(bookShelves);
            if (Globals.getInstance().thread != null && Globals.getInstance().thread.isAlive()) {
                Globals.getInstance().thread.interrupt();
            }
            Globals.getInstance().thread = new Thread(() -> {
                List<BookShelf> bookShelfList = Globals.getInstance().getBookShelves();
                clearAllBookShelf();
                for (int i = 0; i < bookShelfList.size(); i++) {
                    BookShelf bookShelf = bookShelfList.get(i);
                    if (bookShelf.getType().compareTo(BookShelf.TYPE_FOLDER) == 0) {
                        for (int j = 0; j < ((BookShelf_FolderBean) bookShelf).getChildCount();
                            j++) {
                            BookShelf
                                .createWithOutCheck(((BookShelf_FolderBean) bookShelf).getChild(j));
                        }
                    }
                    BookShelf.createWithOutCheck(bookShelf);
                }
            });
            Globals.getInstance().thread.start();
        }


        private void clearAllBookShelf() {
            BookShelf.deleteForAll();
        }

本身这里没有把thread写成静态内部类,只是new了一个Thread,然后重写了run方法,但是根据LeakCanary的报告这里出现了内存泄漏

 

分析:

这是个长期存在的thread,发生内存泄漏的话应该thread持有了该fragment的对象。可是重新阅读代码发现并没有显示的持有该fragment的某个对象。经过漫长的排查....发现其中的某行代码clearAllBookShelf();是问题所在,thread中使用了类的成员方法,成员方法是需要fragment对象调用的,因此持有了fragment实例。尽管clearAllBookShelf();方法中并没有持有实例。

 

解决办法:

可以见到clearAllBookShelf();方法中BookShelf.deleteForAll();是一个其他类中的静态方法。将thread中对clearAllBookShelf();的调用直接替换成BookShelf.deleteForAll();。

 

见到这里突然对静态内部类避免内存泄漏有了深一点的理解,拿这个例子来说,虽然不使用静态内部类可以解决内存泄漏。但是我们使用静态内部类的话就可以直接避免这个问题了,静态内部类中不会允许我们调用外部类的成员方法,就也不会如此“秘密”地持有fragment的实例了,恰巧这个例子中还是一个thread生命周期比fragment更久的情况,导致fragment无法被回收,引发了内存泄漏了。

 

相关标签: 内存泄漏