关于内存泄漏和内存分析检测的简单描述

一、内存泄漏
首先,解释一下内存泄漏是什么。大家都知道jvm内存结构中,分为了heap区和stack区。而我们写程序过程中,经常使用到的对象,在jvm内存结构中被分为了两部分来存储:分别是引用和对象本身的内容。
如:Integer a=new Integer(3);在这个对象的使用中,a是引用,保存在stack区,而对象本身的内容:new Integer(3),则是保存在了heap区(对象和数组对象的元素都保存在heap区中)。
即生成一个对象便会占用一个heap的空间,那么我们的对象在什么时候被jvm回收掉呢?当然是对象没有用的时候就被回收掉了,而jvm中,判断这个对象有没用,是根据这个对象是否有引用指向来判断。(jvm中使用有向图的方式来描述,若一个对象不可达,则没有引用指向了,则可以被回收)。也就是说,在内存足够的情况下,如果一个对象持有(强)引用,则永远不会被回收掉。这,就是内存泄漏的前提了。
而,如果我们在写程序过程中,出现了,逻辑上这个对象a已经没有用了,我们希望其被gc回收掉,但这个对象a任然持有某个引用,导致gc无法对其进行回收,这时,就发生了内存泄漏。简单来说,就是理应被删除掉的对象任然持有某个引用,则发生了内存泄漏。
一次内存泄漏是小事,但是如果经常发生内存泄漏,则迟早会因heap控件不足,而引起内存溢出。这问题就很严重了。
引起内存泄漏的原因有很多,如list、map对象使用完之后没有清除掉集合内容啊,一个类持有了自己非静态内部类的静态引用啊,匿名内部类、线程周期大于外部类啊。。。等等。。。这里就不一一列举了。
二、内存泄漏检测
检测内存泄漏的方法,我主要了解到以下两种:
(1)使用mat工具检测内存泄漏,大致步骤分为:

  • 在容易发生内存泄漏的大致范围内,进行可能引起内存泄漏的操作,然后导出hprof文件。
  • 通过对比hprof文件对程序进行分析,查看某个对象是否应该已被回收,但然仍持有引用,如果有,那此处便发生了内存泄漏。

(2)使用LeakCanary:
leakcanary能否在内存泄漏时即输出内存泄漏的位置、对象等相关信息。使得内存泄漏的检测更加方便。需要在程序中使用leakcanary的相关库的函数来进行检测:

  • 对activity进行监测,leakcanary能够自动监测activity泄漏,只需在activity中对leakcanary进行安装,并返回得到一个RefWather对象,即可通过RefWather对象对其他对象进行监视了:

TestAcitivity extends Activity
{
    private RefWatcher refwatcher;
    oncreate(Bundle b)
    {
        super.oncreate(b);
        setContentView(R.layout.main);
        redwatcher=LeakCanary.install(this);

    }
}

此时,若activity调用ondestory后任然持有应用。则logcat会打印相关日志,通过日志,即可知道哪里泄露了。
通过refwatcher.watch(someobj);也可监视someobj对象是否发生内存泄漏。

简单分析一下LeakCanary的运行过程。当我们调用watch函数监视某个对象时,refwatcher会对传入的参数创建一个weakreference,然后在AndroidWatchExecutor的后台线程中,检测weakreference是否为空,如果不为空,则调用gc回收一次。如果gc后弱引用对象任然存在,则说明内存泄漏,输出hprof文件。然后LeakCanary再通过分析hprof文件(这个过程很复杂),简单说来,就是通过分析,找到弱引用最近的强引用,并将泄漏信息传给一个service,通过service对信息进行打印。

(3)看到还有一种比较粗略的检查内存泄漏的方法,就是打开ddms,观察heap内存的大小,若对某个操作进行多次,执行、再取消的操作,若每次操作后,heap的占用内存都比上次多,则说明内存泄露了。但是具体在哪儿、哪个对象,只有自己去对代码进行单步调试,或者重新行走一遍代码,才能知道了。
以上就是今天学习内存泄漏的总结。仅以此记录一下。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值