查看Android系统,单个进程、多个进程内存的使用情况,通常有那些方法:
1,通过Android API函数
使用ActivityManager查看可用内存,具体是其内部类MemoryInfo。
ActivityManager.MemoryInfo memInfo = new ActivityManager.MemoryInfo();
am.getMemoryInfo(memInfo);
然后通过实例meminfo中的变量读取相关内存信息,如:
public long availMem;
public long totalMem;
public boolean lowMemory; //表示系统是否处于低内存
public long threshold; //表示系统剩余内存低于多少时,认为是低内存。
另外,framework/base/core/java/android/os/Debug.java中,也有一个MemoryInfo内部类,通过它可以查询PSS,VSS,USSS等单个进程使用内存的信息,如:
int appPID = Process.myPid();
int pids[] = new int[1];
pids[0] = appPID;
Debug.MemoryInfo[] memoryInfoArray = mActivityManager.getProcessMemoryInfo(pids);
totalPrivateDirty = memoryInfoArray[0].getTotalPrivateDirty() / BYTES_IN_KILOBYTE;
totalSharedDirty = memoryInfoArray[0].getTotalSharedDirty() / BYTES_IN_KILOBYTE;
totalPSS = memoryInfoArray[0].getTotalPss() / BYTES_IN_KILOBYTE;
nativePSS = memoryInfoArray[0].nativePss / BYTES_IN_KILOBYTE;
dalvikPSS = memoryInfoArray[0].dalvikPss / BYTES_IN_KILOBYTE;
otherPSS = memoryInfoArray[0].otherPss / BYTES_IN_KILOBYTE;
这个方式可以得到比较详细的内存使用情况,单位kb,系统中很多内存是进程间共享的,所以某个进程具体使用多少内存是很难精确统计的:
/** The proportional set size for dalvik heap. (Doesn't include other Dalvik overhead.) */
public int dalvikPss;
/** The proportional set size that is swappable for dalvik heap. */
/** @hide We may want to expose this, eventually. */
public int dalvikSwappablePss;
/** The private dirty pages used by dalvik heap. */
public int dalvikPrivateDirty;
/** The shared dirty pages used by dalvik heap. */
public int dalvikSharedDirty;
/** The private clean pages used by dalvik heap. */
/** @hide We may want to expose this, eventually. */
public int dalvikPrivateClean;
/** The shared clean pages used by dalvik heap. */
/** @hide We may want to expose this, eventually. */
public int dalvikSharedClean;
/** The dirty dalvik pages that have been swapped out. */
/** @hide We may want to expose this, eventually. */
public int dalvikSwappedOut;
/** The dirty dalvik pages that have been swapped out, proportional. */
/** @hide We may want to expose this, eventually. */
public int dalvikSwappedOutPss;
/** The proportional set size for the native heap. */
public int nativePss;
/** The proportional set size that is swappable for the native heap. */
/** @hide We may want to expose this, eventually. */
public int nativeSwappablePss;
/** The private dirty pages used by the native heap. */
public int nativePrivateDirty;
/** The shared dirty pages used by the native heap. */
public int nativeSharedDirty;
/** The private clean pages used by the native heap. */
/** @hide We may want to expose this, eventually. */
public int nativePrivateClean;
/** The shared clean pages used by the native heap. */
/** @hide We may want to expose this, eventually. */
public int nativeSharedClean;
/** The dirty native pages that have been swapped out. */
/** @hide We may want to expose this, eventually. */
public int nativeSwappedOut;
/** The dirty native pages that have been swapped out, proportional. */
/** @hide We may want to expose this, eventually. */
public int nativeSwappedOutPss;
/** The proportional set size for everything else. */
public int otherPss;
/** The proportional set size that is swappable for everything else. */
/** @hide We may want to expose this, eventually. */
public int otherSwappablePss;
/** The private dirty pages used by everything else. */
public int otherPrivateDirty;
/** The shared dirty pages used by everything else. */
public int otherSharedDirty;
/** The private clean pages used by everything else. */
/** @hide We may want to expose this, eventually. */
public int otherPrivateClean;
/** The shared clean pages used by everything else. */
/** @hide We may want to expose this, eventually. */
public int otherSharedClean;
/** The dirty pages used by anyting else that have been swapped out. */
/** @hide We may want to expose this, eventually. */
public int otherSwappedOut;
/** The dirty pages used by anyting else that have been swapped out, proportional. */
/** @hide We may want to expose this, eventually. */
public int otherSwappedOutPss;
/** Whether the kernel reports proportional swap usage */
/** @hide */
public boolean hasSwappedOutPss;
其中Dalvik: 是dalvik所使用的内存;
native :是被native堆使用的内存,通常指使用c/c++在堆上分配的内存。
other: 指除去dalvik,native使用的内存,比如分配在栈上的内存。
private: 指私有的,非共享的
share:指共享的内存。
privateDirty: 指非共享的,又不能换页出去的内存大小,如linux为了提高分配内存速度而缓冲的小对象,即使进程结束,该内存也不会释放,只是又重新回到缓冲中。
sharedDirty :指共享的,又不能换页出去的内存大小。
MemoryInfo 描述的内存使用情况可以通过命令adb shell dumpsys meminfo processName/ID得到。
通过public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids) @ActivityManager.java可以同时得到多个进程的内存使用情况。
通过public static native void getMemInfo(long[] outSizes)@Debug.java得到单个进程的内存使用情况。
通过public List
2,直接对Android文件进行解析
Android严格说只是一个在linux内核上跑的应用程序,所以一般应用程序的内存使用还是采用Linux的传统方法,因此能通过 proc/ 文件系统的meminfo来分析系统的内存使用情况。/proc/cpuinfo中保存了cpu的相关信息,/proc/meminfo/中保存了系统内存的使用信息。比如proc/meminfo中的信息:
MemTotal : ***kb
MemFree: **kb
Buffers :**kb
Cached :** kb
系统在运行过程中memfree通过很小,以为系统会尽可能地cache和buffer一些数据,提高下次执行的速度,但是实际这些内存也是可以随时被拿来使用的,所以空闲内存通常是free+cached+buffers,也即是total-used。
3,通过Runtime类查看
通过Android系统的Runtime类,然后执行adb 命令(top,procrank,ps等)可以实现查询功能,通过将执行结果进行解析,就扩展了Android的查询功能。如:
public String captureMediaserverInfo() {
String cm = "ps mediaserver";
String memoryUsage = null;
int ch;
try {
Process p = Runtime.getRuntime().exec(cm);
InputStream in = p.getInputStream();
StringBuffer sb = new StringBuffer(512);
while ((ch = in.read()) != -1) {
sb.append((char) ch);
}
memoryUsage = sb.toString();
} catch (IOException e) {
Log.v(TAG, e.toString());
}
String[] poList = memoryUsage.split("\r|\n|\r\n");
// A new media.log is enabled with ro.test_harness is set.
// The output of "ps mediaserver" will include the
// media.log process in the first line. Update the parsing
// to only read the thrid line.
// Smaple ps mediaserver output:
// USER PID PPID VSIZE RSS WCHAN PC NAME
// media 131 1 13676 4796 ffffffff 400b1bd0 S media.log
// media 219 131 37768 6892 ffffffff 400b236c S /system/bin/mediaserver
String memusage = poList[poList.length-1].concat("\n");
return memusage;
}
类似的命令"system/bin/top -n l","system/bin/procrank",内存消耗的表示:
VSS:virtual set size ,虚拟耗用内存(包含共享库占用的内存)。
RSS: Resident Set Size ,实际使用物理内存(包含共享库占用的内存)。
PSS:Proportional Set Size,实际使用的物理内存(比例分配共享库占用的内存)。
USS:Unique Set Size,进程独自占用的物理内存(不包括共享库占用的内存)。
4,通过DDMS工具(Dalvik debug Monitor Service)
可以查看内存,cpu的使用情况。
选中要检测的进程,单击Update Heap 图标,然后点击Heap试图中的 CauseGC按钮,在Heap试图中可以看到当前选中进程的内存使用情况。
5,使用Debug的方法
public static native long getNativeHeapSize(); //返回当前进程native堆总的内存大小。
public static native long getNativeHeapFreeSize();//返回当前native堆中剩余内存大小。
public static native long getNativeHeapAllocatedSize();//返回当前进程native堆中已使用内存大小。
6,使用 adb shell procrank命令,查看所有进程的内存使用情况。
配合procrank,使用top命令查看某个进程的内存,可以创建一个脚本memRecord.sh,作用是指定程序每隔一秒输出某个进程的内存使用情况:
#! /bin/bash
while true; do
adb shell procrank | grep "com.android.gallery"
sleep 1
done
使用top命令查看内存具体为:
adb shell top -m 10 //查看使用资源最多的10个进程
adb shell top | grep com.android.gallery //查看gallery进程的内存
free 命令,用来显示内存的使用情况,格式:
free [-b -k -m ] [ -o ] [ -s delay] [ -t ] [ -v]
参数:-b -k -m 表示分别以字节(kb,mb)为单位显示内存使用情况
参数:-s delay ,表示每隔多少秒来显示一次内存使用情况
参数:-t ,显示内存总和列
参数:-o ,不显示缓冲区调节列