【声明:转载请注明出处,谢谢合作!问题联络请发邮件到 bennyyang2008@hotmail.com】
在Android开发中,有时我们需要获取实时的系统信息,方便分析应用的资源占用,内存优化。
以获取CPU使用情况为例,总结如下:
一. 通过查看/proc/meminfo文件,获取内存相关信息。
1. 命令行方式
1) 命令行运行 【adb shell】 命令。
2) 运行【 cat /proc/meminfo】命令,如下内容显示。
# cat /proc/meminfo
cat /proc/meminfo
MemTotal: 126608 kB
MemFree: 2828 kB
Buffers: 72 kB
Cached: 65788 kB
SwapCached: 0 kB
Active: 47176 kB
Inactive: 63428 kB
Active(anon): 25012 kB
Inactive(anon): 30324 kB
Active(file): 22164 kB
Inactive(file): 33104 kB
Unevictable: 280 kB
Mlocked: 0 kB
SwapTotal: 0 kB
SwapFree: 0 kB
Dirty: 0 kB
Writeback: 0 kB
AnonPages: 45036 kB
Mapped: 44412 kB
Slab: 3636 kB
SReclaimable: 924 kB
SUnreclaim: 2712 kB
PageTables: 5156 kB
NFS_Unstable: 0 kB
Bounce: 0 kB
WritebackTmp: 0 kB
CommitLimit: 63304 kB
Committed_AS: 1971508 kB
VmallocTotal: 843776 kB
VmallocUsed: 15464 kB
VmallocChunk: 825348 kB
#
下面先对"/proc/meminfo"文件里列出的字段进行粗略解释:
MemTotal: 所有可用RAM大小。
MemFree: LowFree与HighFree的总和,被系统留着未使用的内存。
Buffers: 用来给文件做缓冲大小。
Cached: 被高速缓冲存储器(cache memory)用的内存的大小(等于diskcache minus SwapCache)。
SwapCached:被高速缓冲存储器(cache memory)用的交换空间的大小。已经被交换出来的内存,仍然被存放在swapfile中,用来在需要的时候很快的被替换而不需要再次打开I/O端口。
Active: 在活跃使用中的缓冲或高速缓冲存储器页面文件的大小,除非非常必要,否则不会被移作他用。
Inactive: 在不经常使用中的缓冲或高速缓冲存储器页面文件的大小,可能被用于其他途径。
SwapTotal: 交换空间的总大小。
SwapFree: 未被使用交换空间的大小。
Dirty: 等待被写回到磁盘的内存大小。
Writeback: 正在被写回到磁盘的内存大小。
AnonPages:未映射页的内存大小。
Mapped: 设备和文件等映射的大小。
Slab: 内核数据结构缓存的大小,可以减少申请和释放内存带来的消耗。
SReclaimable:可收回Slab的大小。
SUnreclaim:不可收回Slab的大小(SUnreclaim+SReclaimable=Slab)。
PageTables:管理内存分页页面的索引表的大小。
NFS_Unstable:不稳定页表的大小。
...
2. 编程实现
/**
* Get the memory info
* by read the file [/proc/meminfo]
*
* @author benny Yang at 2012/03/15
* e-mail: bennyyang2008@hotmail.com
* @return HashMap<String, String>
*/
private HashMap<String, String> getMemoryInfo() {
HashMap<String, String> hmMeminfo = new HashMap<String, String>();
// 系统内存信息文件
String meminfoPath = "/proc/meminfo";
BufferedReader br = null;
try {
FileReader fr = new FileReader(meminfoPath);
br = new BufferedReader(fr, 4096);
String lineStr = null;
while ((lineStr = br.readLine()) != null) {
// 空格区分 分为三部分
// 1. 属性名: 2.数值 3.kB
// eg. MemTotal: 126608 kB
String[] lineItems = lineStr.split("\\s+");
if (lineItems != null && lineItems.length == 3) {
// 去掉[:]
String itemName = lineItems[0].substring(0, lineItems[0].length() - 1);
// 单位是KB,乘以1024转换为Byte,
long itemMemory = Integer.valueOf(lineItems[1]) * 1024;
// Byte转换为KB或者MB,内存大小规格化
String itemValue = Formatter.formatFileSize(getBaseContext(), itemMemory);
hmMeminfo.put(itemName, itemValue);
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (br != null) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
// 打印CPU信息
Log.i("benny", hmMeminfo.toString());
return hmMeminfo;
}
打印信息如下:
{VmallocUsed=18.09MB, CommitLimit=61.82MB, MemTotal=124MB, Writeback=0.00B, SwapFree=0.00B, Inactive=50.98MB, Mlocked=0.00B, Unevictable=280KB, Cached=52.60MB, NFS_Unstable=0.00B, SReclaimable=1.04MB, Mapped=38.86MB, Bounce=0.00B, Buffers=1.05MB, WritebackTmp=0.00B, SUnreclaim=2.82MB, Inactive(anon)=29.53MB, VmallocChunk=798MB, PageTables=5.93MB, Active(file)=26.11MB, SwapTotal=0.00B, MemFree=6.53MB, VmallocTotal=824MB, AnonPages=49.46MB, Active(anon)=25.71MB, SwapCached=0.00B, Active=51.82MB, Slab=3.86MB, Inactive(file)=21.46MB, Committed_AS=-1865285632.00B, Dirty=0.00B}
二. 通过java的反射机制,获取内存相关信息。
/**
* Get the memory info
* by [android.os.Process] 's reflection
*
* @author benny Yang at 2012/03/15
* e-mail: bennyyang2008@hotmail.com
* @return HashMap<String, String>
*/
private HashMap<String, String> getMemoryInfo() {
HashMap<String, String> hmMeminfo = new HashMap<String, String>();
Method _readProclines = null;
try {
Class procClass = Class.forName("android.os.Process");
Class parameterTypes[] = new Class[] { String.class, String[].class, long[].class };
_readProclines = procClass.getMethod("readProcLines", parameterTypes);
Object arglist[] = new Object[3];
final String[] mMemInfoFields = new String[] { "MemTotal:", "MemFree:", "Buffers:", "Cached:" };
long[] mMemInfoSizes = new long[mMemInfoFields.length];
mMemInfoSizes[0] = 30;
mMemInfoSizes[1] = -30;
arglist[0] = new String("/proc/meminfo");
arglist[1] = mMemInfoFields;
arglist[2] = mMemInfoSizes;
if (_readProclines != null) {
_readProclines.invoke(null, arglist);
for (int i = 0; i < mMemInfoSizes.length; i++) {
// 去掉[:]
String itemName = mMemInfoFields[i].substring(0, mMemInfoFields[i].length() - 1);
// Byte转换为KB或者MB,内存大小规格化
String itemValue = Formatter.formatFileSize(getBaseContext(), mMemInfoSizes[i]);
// 把属性和对应的数值放入HashMap.
hmMeminfo.put(itemName, itemValue);
}
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
Log.i("benny", hmMeminfo.toString());
return hmMeminfo;
}
打印信息如下,与方法一同:
{VmallocUsed=18.09MB, CommitLimit=61.82MB, MemTotal=124MB, Writeback=0.00B, SwapFree=0.00B, Inactive=50.98MB, Mlocked=0.00B, Unevictable=280KB, Cached=52.60MB, NFS_Unstable=0.00B, SReclaimable=1.04MB, Mapped=38.86MB, Bounce=0.00B, Buffers=1.05MB, WritebackTmp=0.00B, SUnreclaim=2.82MB, Inactive(anon)=29.53MB, VmallocChunk=798MB, PageTables=5.93MB, Active(file)=26.11MB, SwapTotal=0.00B, MemFree=6.53MB, VmallocTotal=824MB, AnonPages=49.46MB, Active(anon)=25.71MB, SwapCached=0.00B, Active=51.82MB, Slab=3.86MB, Inactive(file)=21.46MB, Committed_AS=-1865285632.00B, Dirty=0.00B}