美文网首页
Java内存泄露知识点

Java内存泄露知识点

作者: 暴走的Jacky | 来源:发表于2017-10-25 11:31 被阅读0次

java的内存分配

  • 静态存储区: 编译时已经分配好内存,在程序整个运行期间都存在,主要存放静态数据和常量
  • 栈区:当方法执行时,会在栈区中创建方法内部的局部变量,方法结束后自动释放内存
  • 堆区:通常用来存放new出来的对象,由java垃圾回收器回收

内存泄露分析

永远的singleton
由于单例的静态特性,使得它的生命周期和应用的生命周期一样长。当我们使用单例的时候,要注意它内部持有的引用,如Activity(导致Activity不能被回收)

public class Singleton{
    private static Singleton singleton;
    private Context context;
    
    private Singleton(Context context){
        this.context=context;
    }
    
    public static Singleton getInstance(Context context){
        if(singleton==null){
            singletoon=new Singleton(context);
        }
        return singleton;
    }
}

如果该单例中需要一个Context,那么确保不要持有Activity的引用,可以使用Application提供的Context。

让人心塞的handler
handler一般作为Acvivity的非静态内部类被创建,那么他就持有了Activity的引用,当我们发送一个延迟消息的时候,Message持有hanlder的引用,而handler持有Activity的引用,所以,当我们主动调用finish()方法的时候,Activity并不会被回收。而如果我们在Activity中需要引用外部的非static对象,应该通过弱引用传入。

public class DemoActivity extends Activity{
    private static final class MyHandler extends Handler{
        private final WeakReference<DemoActivity> mActivity;
        
        public MyHandler(DemoActivity activity){
            this.mActivity=new WeakReference<DemoActivity>(activity);
        }
        @override
        public void handleMessage(Message msg){
            DemoActivity activity=mActivity.get();
            if(activity!=null){
                //do sonmething
            }
        }
    }
    
    private final MyHandler handler=new MyHandler(this);
}

静态内部类不会持有外部类的引用,推荐使用静态内部类+弱引用,每次使用时注意进行非空判断。

同时,在Activity被销毁时,可以清空MessageQueue中的消息。

匿名内部类/非静态内部类
一般在Activity、Fragment或者View中创建内部类,如果是非静态内部类,则会持有外部类的引用。
而如果这个内部类被异步线程所引用,则很可能导致内存泄露。

public class DemoActivity extends Activity{
    private static TestInnerBad testInnerBad=null;
    
    class TestInnerBad{}
    
    @override
    public void onCreate(Bundle bundle){
        
        if(testInnerBad==null){
            testInnerBad=new TestInnerBad();  //内存泄露
        }
        Runnable r1=new Runnable(){   //可能内存泄露
            @override
            public void run(){
                    
            }
        }
        Runnable r2=new MyRunnable();
    }
    
    private static class MyRunnable implements Runnable{
        @override
        public void run(){}
    }
}

TestInnerBad是DemoActivity的内部类,持有他的引用,而它又被声明为static,那么他的生命周期就和App一样,那么肯定是造成了DemoActivity无法被正确的回收。对静态类的正确处理方法是---单独抽取出来封装成一个单例。

r1是DemoActivity的匿名内部类,他持有DemoActivity的引用,而如果r1被传入到一个异步线程中,则很可能造成内存泄露。

集合对象的清除
如果这个集合是static,那么该集合会一直持有传入对象的引用,一般要在Activity、Fragment被销毁时将集合清空。

相关文章

  • Java弱引用学习 WeakHashMap、ReferenceQ

    上一篇文章 Java内存泄露学习 ThreadLocal真的会内存泄露吗 提到ThreadLocal内存泄露的问题...

  • Java内存泄漏

    本文将会介绍: C++中的内存泄露 Java内存管理与垃圾回收 Java中的内存泄漏 一、C++中的内存泄露 在大...

  • Java内存泄露知识点

    java的内存分配 静态存储区: 编译时已经分配好内存,在程序整个运行期间都存在,主要存放静态数据和常量 栈区:当...

  • Android使用Handler造成内存泄露的分析及解决方法

    阅读目录 一、什么是内存泄露? 二、内存泄露的危害 三、解决方案 四、总结 一、什么是内存泄露? Java使用有向...

  • troubleshoot之:使用JFR解决内存泄露

    简介 虽然java有自动化的GC,但是还会有内存泄露的情况。当然java中的内存泄露跟C++中的泄露不同。 在C+...

  • 人生苦短,我学java之内存泄露

    本文详细地介绍了Java内存管理的原理,以及内存泄露产生的原因,同时提供了一些列解决Java内存泄露的方案,希望对...

  • MAT使用进阶

    Java的内存泄露 Java中的内存泄露主要特征:可达,无用 无用指的是创建了但是不再使用之后没有释放 能重用但是...

  • JVM监控与调优:MAT使用进阶

    Java的内存泄露 Java中的内存泄露主要特征:可达,无用 无用指的是创建了但是不再使用之后没有释放 能重用但是...

  • 深入Android内存泄露

    深入内存泄露 android应用层的内存泄露,其实就是java虚拟机的内存泄漏.(这里,暂不讨论C/C++本地内存...

  • JVM之内存模型

    Java内存内存区域图 内存泄露和内存溢出的区别 内存泄露是指分配出去的内存没有被回收回来 内存溢出是指程序所需要...

网友评论

      本文标题: Java内存泄露知识点

      本文链接:https://www.haomeiwen.com/subject/xvcqpxtx.html