android OutOfMemory时抓取heap快照

(这里不教你如何分析heap快照,只说明如何在关键时候抓取)
首先说一下,在程序没有崩溃的时候如何抓取heap快照。
这个大家应该都知道,在ddms中自带此功能。

5ec09800-7852-3a5d-8853-2c56238aa20e.png (77.08 KB, 下载次数: 0)

下载附件 保存到相册

2012-8-28 13:40 上传

见上图
首先我们选中一个进程,然后点击 Update Heap按钮

e5af6ac4-dd94-3e99-a3eb-70c333009987.png (525 Bytes, 下载次数: 0)

下载附件 保存到相册

2012-8-28 13:40 上传

(小绿虫子旁边的按钮),这时就能看到heap使用情况
如果想取出快照详细分析,我们可以点击 Dump HPROF File按钮

673f5526-1d0f-3037-97d2-cf95dc6099ae.png (644 Bytes, 下载次数: 0)

下载附件 保存到相册

2012-8-28 13:40 上传

,保存到电脑上面。使用android-sdk/tools/hprof-conv这个工具把文件转换一下,之后用MAT分析即可。
Java代码
[mw_shl_code=java,true]hprof-conv '/home/su1216/data.hprof' '/home/su1216/data_ok.hprof'[/mw_shl_code]

这时MAT能直接打开data_ok.hprof文件。


如果想要OOM时的内存快照该怎么办,我们总不能紧盯着手机的同时再盯着电脑,OOM出现的瞬间抓取内存快照,这显然是不现实的。
如果OOM并不经常复现,那么我们会错过很多修改bug的机会,浪费很多时间。

下面给大家一种抓取OOM时的heap快照的方法
由于OOM时的heap快照较大,所以抓取的内存快照我选择保存到sd卡中,因此要有写入外部存储的权限
Xml代码


[mw_shl_code=java,true]<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>[/mw_shl_code]


然后我们需要实现UncaughtExceptionHandler这个接口
记得要设置未捕获异常的Handler,设置为自己。
当出现了异常的时候,uncaughtException方法会被调用,所以如果我们可以在这里抓取内存快照。
Java代码


[mw_shl_code=java,true]import java.lang.Thread.UncaughtExceptionHandler;

import android.os.Debug;
import android.os.Environment;
import android.util.Log;

public class CrashHandler implements UncaughtExceptionHandler {

        public static final String TAG = "CrashHandler";
        private Thread.UncaughtExceptionHandler mDefaultHandler;
        private static final String OOM = "java.lang.OutOfMemoryError";
        private static final String HPROF_FILE_PATH = Environment.getExternalStorageDirectory().getPath() + "/data.hprof";

        private static CrashHandler sCrashHandler;

        private CrashHandler() {}

        public synchronized static CrashHandler getInstance() {
                if (sCrashHandler == null) {
                        sCrashHandler = new CrashHandler();
                }
                return sCrashHandler;
        }

        public void init() {
                mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
                Thread.setDefaultUncaughtExceptionHandler(this);
        }

        public static boolean isOOM(Throwable throwable){
                Log.d(TAG, "getName:" + throwable.getClass().getName());
                if(OOM.equals(throwable.getClass().getName())){
                        return true;
                }else{
                        Throwable cause = throwable.getCause();
                        if(cause != null){
                                return isOOM(cause);
                        }
                        return false;
                }
        }
       
        public void uncaughtException(Thread thread, Throwable throwable) {
                if(isOOM(throwable)){
                        try {
                                Debug.dumpHprofData(HPROF_FILE_PATH);
                        } catch (Exception e) {
                                Log.e(TAG, "couldn’t dump hprof", e);
                        }
                }

                if (mDefaultHandler != null) {
                        mDefaultHandler.uncaughtException(thread, throwable);
                } else {
                        android.os.Process.killProcess(android.os.Process.myPid());
                        System.exit(1);
                }
        }
}[/mw_shl_code]


最关键的代码是这句
Java代码


[mw_shl_code=java,true]Debug.dumpHprofData(<span style="line-height: 18px; text-align: left;">HPROF_FILE_PATH</span>);[/mw_shl_code]


使得我们可以自己控制抓取heap快照的时机
OutOfMemoryError是系统级别的错误,所以一般情况下不该捕获它。
万一有人捕获了,并且重新抛出了一个调用了initCause方法的异常,我们也应该截获它,然后修正bug,而不是掩藏它。

我们在这里只是需要抓取内存快照,干完活之后要记得把throwable交给系统来处理
Java代码


[mw_shl_code=java,true]mDefaultHandler.uncaughtException(thread, throwable);[/mw_shl_code]


当然,我们在这个地方实际上也可以屏蔽掉force close对话框,很神奇吧。。。

结尾顺便说一下,如何查看android对应用的内存限制
每款手机对应用的限制都是不一样的,毕竟硬件不同,我们可以使用如下方式来查看单独的应用可使用的最大内存:
Shell代码


[mw_shl_code=java,true]adb shell getprop | grep heap
[dalvik.vm.heapgrowthlimit]: [64m]
[dalvik.vm.heapsize]: [256m]
[dalvik.vm.heapstartsize]: [8m][/mw_shl_code]


输入命令之后回查到上述几个结果
[dalvik.vm.heapstartsize]: [8m]:给进程分配的起始heap=8m
[dalvik.vm.heapgrowthlimit]: [64m]:进程最大可分配到64m
[dalvik.vm.heapsize]: [256m]:单个虚拟机可分配的最大内存=256m

更改上述参数可以在build.prop修改
build.prop在system下,pull出来修改后再push回去,reboot即可


我们可以根据这个来估计heap的大小,检查sd卡剩余空间是否够用。

转自:http://www.apkbus.com/android-66007-1-1.html
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值