Android进程内存查看

Android进程内存查看

1、使用场景(内存)

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

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

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

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

1)命令:adbshell dumpsys meminfo yourpakagename

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

Android进程内存查看_第1张图片

改命令实际的调用代码入口在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

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

Android进程内存查看_第2张图片

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.csdn.net/itachi85/article/details/77075455
https://blog.csdn.net/yxz329130952/article/details/50288145

你可能感兴趣的:(android)