android 内存使用
来源:互联网 发布:三一学院 知乎 编辑:程序博客网 时间:2024/06/05 15:25
smem
http://elinux.org/Using_smem_on_Android
android 内存使用
众所周知,在写 android 程序的时候,很容易出现 OOM ,而出现的时机大多数是由 Bitmap decode 引发的:
ERROR/AndroidRuntime(16350): java.lang.OutOfMemoryError: bitmap size exceeds VM budget
我们知道,android程序内存一般限制在16M,当然也有24M的,而android程序内存被分为2部分:native和 dalvik,dalvik就是我们平常说的java堆,我们创建的对象是在这里面分配的,而bitmap是直接在native上分配的,对于内存的限制是native+dalvik 不能超过最大限制。
用以下命令可以查看程序的内存使用情况:
adb shell dumpsys meminfo $package_name or
$pid //
使用程序的包名或者进程
id
用android自带的launcher程序为例:
01
run: adb shell dumpsys meminfo com.android.launcher
02
<br>results:
03
Applications Memory Usage (kB):
04
Uptime: 113017 Realtime: 113017
05
06
** MEMINFO in
pid 129 [com.android.launcher] **
07
native dalvik other total
08
size: 4572 3527 N/A 8099
09
allocated: 4113 2684 N/A 6797
10
free: 406 843 N/A 1249
11
(Pss): 1775 3572 3953 9300
12
(shared dirty): 1448 4020 4792 10260
13
(priv dirty): 1652 1308 708 3668
14
15
Objects
16
Views: 0 ViewRoots: 0
17
AppContexts: 0 Activities: 0
18
Assets: 5 AssetManagers: 5
19
Local
Binders: 14 Proxy Binders: 21
20
Death Recipients: 0
21
OpenSSL Sockets: 0
22
23
SQL
24
heap: 64 memoryUsed: 64
25
pageCacheOverflo: 4 largestMemAlloc: 50
26
27
DATABASES
28
Pagesize Dbsize Lookaside Dbname
29
1024 4 48 launcher.db
1
native dalvik other total
2
size: 4572 3527 N/A 8099
3
allocated: 4113 2684 N/A 6797
其中size是需要的内存,而allocated是分配了的内存,对应的2列分别是native和dalvik,当总数也就是total这一列超过单个程序内存的最大限制时,OOM就很有可能会出现了。
多数时候,发生OOM都是在做一些跟图片相关的操作,以下提出一些建议尽量可以减少这种情况的发生:
1.decode bitmap
的时候,尽量配置下
Options
,例如:
inSameSize
2.Bitmap
使用完以后,调用
bitmap.recycle()
来释放内存
3.
如果应用是基于图片的应用,尽量采用
LazyLoad
和
DymanicRecycle
4.decode bitmap
的时候,将
decode
代码
try
catch
出来,
catch
oom error
,避免程序
crash
,可以在
catch
里面做一些释放内存操作
http://stackoverflow.com/questions/2298208/how-to-discover-memory-usage-of-my-application-in-android#2299813
Note that memory usage on modern operating systems likeLinux is an extremely complicated and difficult to understand area. Infact the chances of you actually correctly interpreting whatever numbers youget is extremely low.
First thing is to probably read the last part of thisarticle which has some discussion of how memory is managed on Android:
http://android-developers.blogspot.com/2010/02/service-api-changes-starting-with.html
Now ActivityManager.getMemoryInfo()is our highest-level API for looking at overall memory usage. This is mostlythere to help an application gauge how close the system is coming to having nomore memory for background processes, thus needing to start killing neededprocesses like services. For pure Java applications, this should be of littleuse, since the Java heap limit is there in part to avoid one app from beingable to stress the system to this point.
Going lower-level, you can use the Debug API to get raw kernel-levelinformation about memory usage:
Note starting with 2.0 there is also an API, ActivityManager.getProcessMemoryInfo,to get this information about another process:
This returns a low-level MemoryInfo structure with all ofthis data:
/** The proportional set size for dalvik. */ public int dalvikPss; /** The private dirty pages used by dalvik. */ public int dalvikPrivateDirty; /** The shared dirty pages used by dalvik. */ public int dalvikSharedDirty; /** The proportional set size for the native heap. */ public int nativePss; /** 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 proportional set size for everything else. */ public int otherPss; /** The private dirty pages used by everything else. */ public int otherPrivateDirty; /** The shared dirty pages used by everything else. */ public int otherSharedDirty;
But as to what the difference is between "Pss","PrivateDirty", and "SharedDirty"... well now the funbegins.
A lot of memory in Android (and Linux systems in general)is actually shared across multiple processes. So how much memory a processesuses is really not clear. Add on top of that paging out to disk (let alone swapwhich we don't use on Android) and it is even less clear.
Thus if you were to take all of the physical RAM actuallymapped in to each process, and add up all of the processes, you would probablyend up with a number much greater than the actual total RAM.
The Pssnumber is a metric the kernel computes that takes into account memory sharing-- basically each page of RAM in a process is scaled by a ratio of the numberof other processes also using that page. This way you can (in theory) add upthe pss across all processes to see the total RAM they are using, and comparepss between processes to get a rough idea of their relative weight.
The other interesting metric here is PrivateDirty, which isbasically the amount of RAM inside the process that can not be paged to disk(it is not backed by the same data on disk), and is not shared with any otherprocesses. Another way to look at this is the RAM that will become available tothe system when that process goes away (and probably quickly subsumed intocaches and other uses of it).
That is pretty much the SDK APIs for this. However there ismore you can do as a developer with your device.
Using adb, there is a lot of information you can get aboutthe memory use of a running system. A common one is the command "adb shell dumpsys meminfo"which will spit out a bunch of information about the memory use of each Javaprocess, containing the above info as well as a variety of other things. Youcan also tack on the name or pid of a single process to see, for example"adb shell dumpsys meminfo system" give me the system process:
** MEMINFO in pid 890 [system] **
native dalvik other total
size: 10940 7047 N/A 17987
allocated: 8943 5516 N/A 14459
free: 336 1531 N/A 1867
(Pss): 4585 9282 11916 25783
(shared dirty): 2184 3596 916 6696
(priv dirty): 4504 5956 7456 17916
Objects
Views: 149 ViewRoots: 4
AppContexts: 13 Activities: 0
Assets: 4 AssetManagers: 4
Local Binders: 141 Proxy Binders: 158
Death Recipients: 49
OpenSSL Sockets: 0
SQL
heap: 205 dbFiles: 0
numPagers: 0 inactivePageKB: 0
activePageKB: 0
The top section is the main one, where "size" isthe total size in address space of a particular heap, "allocated" isthe kb of actual allocations that heap things it has, "free" is theremaining kb free the heap has for additional allocations, and "pss"and "priv dirty" are the same as discussed before specific to pagesassociated with each of the heaps.
If you just want to look at memory usage across allprocesses, you can use the command "adb shell procrank". Output of this on thesame system looks like:
PID Vss Rss Pss Uss cmdline
890 84456K 48668K 25850K 21284K system_server
1231 50748K 39088K 17587K 13792K com.android.launcher2
947 34488K 28528K 10834K 9308K com.android.wallpaper
987 26964K 26956K 8751K 7308K com.google.process.gapps
954 24300K 24296K 6249K 4824K com.android.phone
948 23020K 23016K 5864K 4748K com.android.inputmethod.latin
888 25728K 25724K 5774K 3668K zygote
977 24100K 24096K 5667K 4340K android.process.acore
...
59 336K 332K 99K 92K /system/bin/installd
60 396K 392K 93K 84K /system/bin/keystore
51 280K 276K 74K 68K /system/bin/servicemanager
54 256K 252K 69K 64K /system/bin/debuggerd
Here the Vss and Rss columns are basically noise (these arethe straight-forward address space and RAM usage of a process, where if you addup the RAM usage across processes you get an ridiculously large number).
Pss is as we've seen before, and Uss is Priv Dirty.
Interesting thing to note here: Pss and Uss are slightly(or more than slightly) different than what we saw in meminfo. Why is that?Well procrank uses a different kernel mechanism to collect its data thanmeminfo does, and they give slightly different results. Why is that? Honestly Ihaven't a clue. I believe procrank may be the more accurate one... but really,this just leave the point: "take any memory info you get with a grain ofsalt; often a very large grain."
Finally there is the command "adb shell cat /proc/meminfo" thatgives a summary of the overall memory usage of the system. There is a lot ofdata here, only the first few numbers worth discussing (and the remaining onesunderstood by few people, and my questions of those few people about them oftenresulting in conflicting explanations):
MemTotal: 395144 kB
MemFree: 184936 kB
Buffers: 880 kB
Cached: 84104 kB
SwapCached: 0 kB
MemTotal is the total amount of memory available to thekernel and user space (often less than the actual physical RAM of the device,since some of that RAM is needed for the radio, DMA buffers, etc).
MemFree is the amount of RAM that is not being used at all.The number you see here is very high; typically on an Android system this wouldbe only a few MB, since we try to use available memory to keep processesrunning
Cached is the RAM being used for filesystem caches andother such things. Typical systems will need to have 20MB or so for this toavoid getting into bad paging states; the Android out of memory killer is tunedfor a particular system to make sure that background processes are killedbefore the cached RAM is consumed too much by them to result in such paging.
void getMemInfo()
{
ActivityManageractivityManager = (ActivityManager) this.getSystemService(ACTIVITY_SERVICE);
MemoryInfo memoryInfo = newActivityManager.MemoryInfo();
activityManager.getMemoryInfo(memoryInfo);
Log.i(TAG, " memoryInfo.availMem " + memoryInfo.availMem + "\n" );
Log.i(TAG, " memoryInfo.lowMemory " + memoryInfo.lowMemory + "\n" );
Log.i(TAG, " memoryInfo.threshold " + memoryInfo.threshold + "\n" );
List<RunningAppProcessInfo> runningAppProcesses =activityManager.getRunningAppProcesses();
Map<Integer,String> pidMap = new TreeMap<Integer, String>();
for(RunningAppProcessInfo runningAppProcessInfo : runningAppProcesses)
{
pidMap.put(runningAppProcessInfo.pid, runningAppProcessInfo.processName);
}
Collection<Integer>keys = pidMap.keySet();
for(int key : keys)
{
int pids[] = new int[1];
pids[0] = key;
android.os.Debug.MemoryInfo[] memoryInfoArray =activityManager.getProcessMemoryInfo(pids);
for(android.os.Debug.MemoryInfo pidMemoryInfo: memoryInfoArray)
{
Log.i(TAG, String.format("**MEMINFO in pid %d [%s] **\n",pids[0],pidMap.get(pids[0])));
Log.i(TAG, "pidMemoryInfo.getTotalPrivateDirty(): " + pidMemoryInfo.getTotalPrivateDirty() + "\n");
Log.i(TAG, " pidMemoryInfo.getTotalPss():" + pidMemoryInfo.getTotalPss() + "\n");
Log.i(TAG, "pidMemoryInfo.getTotalSharedDirty(): " + pidMemoryInfo.getTotalSharedDirty() + "\n");
}
}
}
- android 内存使用
- android app 内存使用
- android 内存使用
- android 内存使用
- android 内存使用
- android 内存使用
- Android内存使用研究
- Android内存使用研究
- Android内存的使用
- Android内存使用研究
- android 内存使用总结
- Android内存的使用
- android有效的内存使用
- Android 查看内存使用情况
- Android 查看内存使用情况
- android回收图片使用内存
- Android 查看内存使用情况
- Android 查看内存使用情况
- BOM展开函数解析
- iOS开源:MYCrypto
- 做总账凭证FB50报错“错误调用功能模块 CHECK_PLANTS_ABROAD_ACTIVE”
- windows xp下配置JDK环境变量
- SAP同一公司不同工厂间物料转储方案比较
- android 内存使用
- 技巧网站锦集
- linux2.6.36以上安装aodv-uu-0.9.6
- C# SerialPort使用方法
- java中String.format的使用
- java 并发包 多线程 工具类 笔记
- ajax后退解决方案(二)
- directadmin 给出快速清空 exim队列的方法
- gallery note