使用Android profiler分析Android native物理内存泄漏

Android内存泄漏有很多种,比如说java堆内存泄漏,native堆内存泄漏,graphic 纹理泄漏等等,其中native泄漏相对比较难以定位,java泄漏可以通过hprof文件分析堆内存定位,比较容易,但是对native泄漏来说,之前的工具都不是特别好用。

之前我们说过可以使用perfetto分析Android native物理内存泄漏,喜大普奔的是,这个功能最近被集成进Android Profiler了,更方便了。

我们用和上次一样的demo说明用法。

内存泄漏demo

我们通过一个简单的例子说明一下。

新建一个简单的cpp工程,通过JNI在activity resume的时候调用了两个测试函数。
可以看到
aaaaaaaaaaaa() malloc了内存,但是没有free,造成了泄漏。
bbbbbbbbbbbb() malloc了内存,有free,没有造成泄漏。

void aaaaaaaaaaaa() {
    for (int i = 0; i < 100000; i++) {
        int *a = (int *) malloc(sizeof(int));
        if (a != NULL) {
            *a = 100;
        }
    }
}
void bbbbbbbbbbbb() {
    for (int i = 0; i < 100000; i++) {
        int *a = (int *) malloc(sizeof(int));
        if (a != NULL) {
            *a = 100;
            free(a);
        }
    }
}
activity resume时调用泄漏函数.png
native 泄漏函数和非泄漏函数.png

显然这个内存泄漏case的复现路径是不停的执行resume,pause。通过Android profiler可以看到native内存确实是不断增长的。

native内存持续上升.png

使用Android Profiler分析native泄漏步骤

1. 编译debug版本的app并运行

2. 点击profiler并选中要调试的进程

点击profiler并选中要调试的进程.png

3. 点击进入memory页面,选中record native allocations并点击record开始录制内存信息。

录制内存.png

4. 重复复现路径,

这段时间内会记录申请和释放的内存信息,后面通过对比就可以发现哪些函数申请了内存没有释放了。

4. 查看内存信息

可以看到函数申请的内存以及函数调用栈都显示出来了。

Total Remaining Size:表示这段时间内函数申请了还没有释放的内存
Alloction Size:表示这段时间内函数申请过的所有内存(包括已经释放的和还没有释放的)

一个函数,如果没有泄漏,那么Alloction Size 会远大于Total Remaining Size
一个函数,如果泄漏了,那么Alloction Size会等于Total Remaining Size

通过对比这2个值在所有函数申请的内存的占比,就可以很容易的找到泄漏的函数。

图中这个例子,aaaaaaaa()函数的Alloction Size占比很小,但Total Remaining Size占比却出奇的大,说明aaaaaaaa()泄漏了。

泄漏的调用栈也打出来了,就很容易解决了。

申请过的所有内存.png
申请了后还没有释放的内存.png

你可能感兴趣的:(使用Android profiler分析Android native物理内存泄漏)