现在的位置: 首页 > 移动开发 > 正文

Android内存问题分析一些命令

2019年10月09日 移动开发 ⁄ 共 4839字 ⁄ 字号 评论关闭

1。 查看当前手机HEAP size 设定

adb shell getprop | grep heap

[dalvik.vm.heapgrowthlimit]: [192m]
[dalvik.vm.heapsize]: [512m]

可以查看到heapsize 的大小

2. 使用procrank 跟踪某个进程的内存

App:Application
VSS ­ Virtual Set Size 虚拟耗用内存(包含共享库占用的内存)
RSS ­ Resident Set Size 实际使用物理内存(包含共享库占用的内存)
PSS ­ Proportional Set Size 实际使用的物理内存(比例分配共享库占用的内存)
USS ­ Unique Set Size 进程独自占用的物理内存(不包含共享库占用的内存)

procrank 命令可以获得当前系统中各进程的内存使用快照,这里有PSS,USS,VSS,RSS。
我们一般观察Uss来反映一个Process的内存使用情况,Uss 的大小代表了只属于本进程正在使
用的内存大小,这些内存在此Process被杀掉之后,会被完整的回收掉,
Vss和Rss对查看某一Process自身内存状况没有什么价值,因为他们包含了共享库的内存使
用,而往往共享库的资源占用比重是很大的,这样就稀释了对Process自身创建内存波动。
而Pss是按照比例将共享内存分割,某一Process对共享内存的占用情况。
procrank 的代码在 /system/extras/procrank,,在模拟器或者设备上的运行文件位/system/xbin
在adb shell之后,我们运行procrank

adb shell procrank

我们还可以使用脚本配合procrank跟踪内存变化
使用procrank来跟踪某进程的使用哪个情况我们常常借助与脚本。这样就可以查看某一段时间
的内存变化。
如创建一个文件:trackmem.sh chmod 775 trackmem.sh
内容如下:
#!/bin/bash
while true; do
adb shell procrank | grep "com.baidu.BaiduReader"
sleep 1
done
运行该脚本:
./trackmem.sh
这个脚本的用途是每1秒钟让系统输出一次BaiduReader的内存使用状况

3. 查看某个进程的内存信息

例如 要查看 com.android.systemui 的内存使用情况

adb shell dumpsys meminfo com.android.systemui

** MEMINFO in pid 1179 [com.android.systemui] **
                   Pss  Private  Private  Swapped     Heap     Heap     Heap
                 Total    Dirty    Clean    Dirty     Size    Alloc     Free
                ------   ------   ------   ------   ------   ------   ------
  Native Heap     7207     7184        0      260     8192     8043       92
  Dalvik Heap    69196    69144        0     1028    72248    69354     2894
 Dalvik Other     2587     2504        0     1012                           
        Stack      156      156        0       16                           
       Ashmem        2        0        0        0                           
    Other dev        5        0        4        0                           
     .so mmap      920      204       20     2688                           
    .apk mmap     1516        0        4        0                           
    .ttf mmap        4        0        0        0                           
    .dex mmap     1272       68      652      136                           
   Other mmap       37        4       28        0                           
      Unknown      108      108        0        8                           
        TOTAL    83010    79372      708     5148    80440    77397     2986
 
 Objects
               Views:      414         ViewRootImpl:        1
         AppContexts:        9           Activities:        0
              Assets:        6        AssetManagers:        6
       Local Binders:       76        Proxy Binders:       48
    Death Recipients:        3
     OpenSSL Sockets:        0
 
 SQL
         MEMORY_USED:        0
  PAGECACHE_OVERFLOW:        0          MALLOC_SIZE:        0

可以查看Native Heap 和 Davilik Heap 使用情况

4。查看GC log

先查看systemui 进程id

adb shell ps | grep systemui

u0_a64    910   195   939612 75312 ffffffff 400aa560 S com.android.systemui

查看 log

adb logcat -v time | grep "910): GC_"

01-01 01:20:22.040 D/dalvikvm(  910): GC_EXPLICIT freed 865K (12243), 51% free 29409K/59320K, paused 6ms+7ms, total 56ms
01-01 01:20:26.497 D/dalvikvm(  910): GC_FOR_ALLOC freed 316K (4580), 44% free 33467K/59320K, paused 49ms, total 49ms

adb logcat -v time -s dalvikvm-heap
01-01 01:21:26.511 I/dalvikvm-heap(  910): Grow heap (frag case) to 64.409MB for 16588816-byte allocatio

1、GC_FOR_ALLOC:发生在堆被占满不能进行内存分配时,在分配新对象之前必须进行内存回收。

2、GC_CONCURRENT:发生在(可能是部分的)垃圾可供回收时,通常有很多对象可以回收。

3、GC_EXPLICIT:显式调用System.gc()产生的垃圾收集。

freed 865K  表示 释放865k 内存, 51% free 29409K/59320K 表示heapsize 是 59M 已用29M 有51%的 free

5 .use MAT 分析 dump hprof 文件

简单介绍一下ShallowHeap和RetainedHeap。
Shallow size就是对象本身占用内存的大小,不包含对其他对象的引用,也就是对象头加成员
变量(不是成员变量的值)的总和。在32位系统上,对象头占用8字节,int占用4字节,不管成
员变量(对象或数组)是否引用了其他对象(实例)或者赋值为null它始终占用4字节。
Retained size是该对象自己的shallow size,加上从该对象能直接或间接访问到对象的shallow
size之和。换句话说,retained size是该对象被GC之后所能回收到内存的总和。

使用MAT

http://blog.csdn.net/yangchuxi/article/details/6780097

http://blog.csdn.net/amy0428/article/details/7057282

http://blog.csdn.net/aaa2832/article/details/19419679

用MAT分析内存泄露

1. 利用Android DDMS dump 当前堆栈的hprof 文件

2. 利用hprof-conv 转换dump出来的hprof 文件

3. 用MAT 打开分析

先点击Histogram 查看 当前堆 里面所有的java object 对象。 可进行排序。查看Retained size 占很高的对象。或者Objects 数量很多的对象。是否是正常行为。

在Histogram  里面进行 过滤 查找。 查找本app 里面的Activity, Fragment 数量个数是否正确。

一种比较容易发生内存泄露的方式。就是由于有一些Activity  或者 Fragment  的内部类 的引用。造成Activity 和 fragment 无法被系统回收

(注意: Java 种  内部类 会 自动持有 外部类的引用。 这样可以调用外部类的成员变量)

所以一般Activity  或者 Fragment 中有内部类的。需要注意内部类的生命周期。比如: BroaderCastReceiver ,  Timer , Thread, Hanlder, Animator的 Listener 等等。

需要特别注意这些对象的生命周期 是否超过了Activity  或者 Fragment  的生命周期

6. 利用CashHandler 自动dump hprof 文件。

为了便于在OOM发生的时候 能够Dump Hprof 文件。 提供分析。可以设置全局的CashHandler  并判断是否OOM ,如果是OOM 则利用

Debug类dump hprof 文件

dumpHprofData(String fileName)

private static final String OOM = "java.lang.OutOfMemoryError";

if (isOOM(arg1)) {
    SimpleDateFormat sDateFormat =
            new SimpleDateFormat("MM_dd_hh_mm_ss");
    String date = sDateFormat.format(new Date());
    File dumpfile = new File(logdir + File.separator + "oom" + date
            + ".hprof");
    Debug.dumpHprofData(dumpfile.getAbsolutePath());
}

public static boolean isOOM(Throwable throwable){
    if(OOM.equalsIgnoreCase(throwable.getClass().getName())){
        return true;
    }else{
        Throwable cause = throwable.getCause();
        if(cause != null){
            return isOOM(cause);
        }
        return false;
    }
}

抱歉!评论已关闭.