Android进程内存查看

本文介绍了Android进程内存查看的多种方法,包括使用adbshell命令dumpsys meminfo和procrank分析内存占用,以及通过代码和工具进行内存检查。重点讨论了VSS、RSS、PSS和USS等内存指标的含义和区别,帮助开发者理解并优化应用内存使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Android进程内存查看

1、使用场景(内存)

1APK启动应用时内存占用及分布,即初始化时(如内核初始化,外围资源加载等)各占多少

2)使用APK核心功能时内存占用及分布,如UI加载,数据加载保存

3)用户常用操作时内存占用及分布

2通过命令查看内存占用及分布

1)命令:adbshell dumpsys meminfo yourpakagename

终端输入命令后,可以看到类似下图的结果


改命令实际的调用代码入口在android.os.Debug.java和对应的CPP文件android_os_Debug.cppDebug.javagetMeminfo方法实际上调用了android_os_Debug.cppandroid_os_Debug_getDirtyPagesPid方法。

	static voidandroid_os_Debug_getDirtyPagesPid(JNIEnv *env, jobject clazz, jintpid, jobject object)

{

stats_tstats[_NUM_HEAP];

memset(&stats,0, sizeof(stats));



load_maps(pid,stats);



structgraphics_memory_pss graphics_mem;

if(read_memtrack_memory(pid, &graphics_mem) == 0) {

...

}



...

}



static voidload_maps(int pid, stats_t* stats)

{

chartmp[128];

FILE *fp;



sprintf(tmp,"/proc/%d/smaps", pid);

fp =fopen(tmp, "r");

if (fp ==0) return;



read_mapinfo(fp,stats);

fclose(fp);

}


           从上面的代码可以看到,android_os_Debug_getDirtyPagesPid方法先调用了load_maps方法,而load_maps方法要做的事情也很简单,它打开/proc/PID/smaps虚拟文件,读取里面的信息,在已ROOT的设备上,我们可以通过“adbshell cat /proce/PID/smaps”直接将这个虚拟文件的信息打印在控制台上。

       “adb shell cat/proce/PID/smaps”输出的信息实际上是应用的userspace地址空间的内存分配表,记录了应用分配的每一块内存的地址,类别,大小等信息,而load_maps方法调用read_mapinfo方法从这个表里面读出每一块内存的分配信息,分类进行累加,得出Native HeapDalvikHeap等各个类别的内存占用。

           更多具体讲解可以参考:http://tech.uc.cn/?p=2714

我们可以使用脚本smaps解析得到更简化的内存数据分布。

2)命令:adbshell procrank

通过该命令可以获取所有进程的内存占用:



linux下表示内存的耗用情况有四种不同的表现形式:
VSS- Virtual Set Size 虚拟耗用内存(包含共享库占用的内存)
RSS- Resident Set Size 实际使用物理内存(包含共享库占用的内存)
PSS- Proportional Set Size 实际使用的物理内存(比例分配共享库占用的内存)
USS- Unique Set Size 进程独自占用的物理内存(不包含共享库占用的内存)

VSSVSS表示一个进程可访问的全部内存地址空间的大小。这个大小包括了进程已经申请但尚未使用的内存空间。在实际中很少用这种方式来表示进程占用内存的情况,用它来表示单个进程的内存使用情况是不准确的。
RSS表示一个进程在RAM中实际使用的空间地址大小,包括了全部共享库占用的内存,这种表示进程占用内存的情况也是不准确的。
PSS表示一个进程在RAM中实际使用的空间地址大小,它按比例包含了共享库占用的内存。假如有3个进程使用同一个共享库,那么每个进程的PSS就包括了1/3大小的共享库内存。这种方式表示进程的内存使用情况较准确,但当只有一个进程使用共享库时,其情况和RSS一模一样。
USS:表示一个进程本身占用的内存空间大小,不包含其它任何成分,这是表示进程内存大小的最好方式!
可以看到:VSS>=RSS>=PSS>=USS



Note:这里有一个问题需要注意,如果一个APK里面只使用了32位的so库文件,在64位的机器上运行,一般系统系统会兼容。但是对应的PSS内存可能会比使用64位的so所占用的内存大。因为在32位共享库占用的内存可能会全部算到该APKPSS内存里面(因为没有其他32APK按比例分配共享库内存)

3通过代码查看内存占用及分布

下面列举几种获取不同内存的方式:

	publicstaticlongusedMemory() {

finalRuntime s_runtime = Runtime.getRuntime();

return(s_runtime.totalMemory() - s_runtime.freeMemory());

}

publicstaticintgetPssMemory(Context context) {

finalActivityManager am = (ActivityManager) context

.getSystemService(Activity.ACTIVITY_SERVICE);

android.os.Debug.MemoryInfo[]memoryInfoArray = am.getProcessMemoryInfo

(newint[]{android.os.Process.myPid()});

returnmemoryInfoArray[0].getTotalPss();

}

/**

*Gets the total available memory (KB) on the system.

*/

publicstaticlonggetTotalAvailableMemory(Context context) {

try{

finalActivityManager am = (ActivityManager) context

.getSystemService(Activity.ACTIVITY_SERVICE);

ActivityManager.MemoryInfooutInfo = newActivityManager.MemoryInfo();

am.getMemoryInfo(outInfo);

return(long)outInfo.availMem/1024;

}catch(Exceptione){

return-1;

}

}

/**

*Gets the total memory (KB) on the system.

*/

publicstaticlonggetTotalMemory(Context context) {

try{

finalActivityManager am = (ActivityManager) context

.getSystemService(Activity.ACTIVITY_SERVICE);

ActivityManager.MemoryInfooutInfo = newActivityManager.MemoryInfo();

am.getMemoryInfo(outInfo);

if(SystemPropertiesReflect.getSdkVersion()>= SystemPropertiesReflect.VERSION_CODES.JELLY_BEAN)

return(long)outInfo.totalMem/1024;

else

return-1;

}catch(Exceptione){

return-1;

}

}


4通过工具查看

android device monitor查看内存使用及分布:
MAT工具分析内存泄露,参考:
https://blog.youkuaiyun.com/itachi85/article/details/77075455
https://blog.youkuaiyun.com/yxz329130952/article/details/50288145
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值