android 常见的oom,Android monkey OOM 问题分析

遇到的问题

android app 经常会遇到 OOM 问题,有些 OOM比较容易解决,比如常见的Activity泄漏导致的 OOM。但是有些OOM自己不是很容易复现,monkey 可以复现。这种情况下我们就需要 monkey OOM情况下的 hprof 文件 来分析。

dump hprof 的几种方法使用 ddms 可以手工dump,这种只能用于手工验证。

adb shell am dumpheap 这个可以实现自动化,参考 源码 /dalvik/docs/heap-profiling.html 中的说明。但是有个问题,此方法对于已经crash 的进程,无法dump。此方法只对 debugable app 有效。

参考 ddms 的实现方法,基于 ddmlib 参考 ddms 源码可以 开发一个命令行工具,也很好用。这种情况用于 monkey 结束后 dump,很不错的方法。且 crash 状态写也可以,因为crash状态下的进程也是 running状态,跟am dumpheap 实现方案不一样。此方法只对 debugable app 有效。

程序源代码调用 Debug.dumpHprofData 函数输出。

考虑到我们的monkey 是 ignore-crash ignore-timeout ,也就是发生异常继续执行。所以这种情况下采用 Debug.dumpHprofData 方式是比较合适的。

Debug.dumpHprofData 方法因为是调试代码,所以只在 debugable 模式下工作,release 代码不生效。

注册 UncaughtExceptionHandler ,如果是 OOM 则 dump 内存 到 /sdcard/bdhprof/ 目录,发生一次生成一个,文件格式 packagename_yyyy-mm-dd-HH-mm-ss.hprof,例如 com.baidu.appsearch_2015-07-28-14-08-11.hprof

Monkey 跑完后,在脚本中添加 adb pull /sdcard/bdhprof/ . 把 hprof 文件 抓取到 本地供分析。然后删除 sdcard中的文件 adb shell rm /sdcard/bdhprof/*

参考代码

public class MainActivity extends ActionBarActivity {

ArrayList cache = new ArrayList();

private UncaughtExceptionHandler defaultCrashHandler;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

Button button = (Button) findViewById(R.id.button);

button.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

defaultCrashHandler = Thread.getDefaultUncaughtExceptionHandler();

Thread.setDefaultUncaughtExceptionHandler(new CrashHandler());

// 模拟 OOM

for (;;) {

byte[] c = new byte[1000*1000];

cache.add(c);

}

}

});

}

public class CrashHandler implements UncaughtExceptionHandler {

@Override

public void uncaughtException(Thread thread, Throwable ex){

if (ex.getClass().equals(OutOfMemoryError.class)) {

// 如果是 oom 异常, dump hprof 到 /sdcard/bdhprof/ 目录下

File dir = new File(Environment.getExternalStorageDirectory().getPath(), "bdhprof");

if (!dir.exists()) {

dir.mkdir();

}

SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");

String fileName = getPackageName() + "_" + format.format(new Date(System.currentTimeMillis()));

File file = new File(dir, fileName + ".hprof");

System.gc();

try {

Debug.dumpHprofData(file.getAbsolutePath());

} catch (IOException e) {

e.printStackTrace();

}

}

// 重新交给系统,抛出dialog 提示异常。

defaultCrashHandler.uncaughtException(thread, ex);

}

}

}

负面影响

dump过程需要时间时间长,此时 monkey 还在继续,所以这时候会产生 anr。 所以分析结果的时候,需要手工过滤掉此类的 anr为正常。

你可能感兴趣的:(android,常见的oom)