android 内存溢出 内存管理

来源:互联网 发布:知乎奇葩病人 编辑:程序博客网 时间:2024/05/03 20:30

http://jcwlw.blog.163.com/blog/static/36773209201111239364514/

http://blog.csdn.net/zzp16/article/details/6719809

http://blog.163.com/jackswu@yeah/blog/static/140629123201112513324705/?fromdm&fromSearch&isFromSearchEngine=yes

http://wenku.baidu.com/view/05b2d31d650e52ea551898f0.html

 

GC_FOR_MALLOC means that the GC was triggered because there wasn't enough memory left on the heap to perform an allocation. Might be triggered when new objects are being created.

GC_EXPLICIT means that the garbage collector has been explicitly asked to collect, instead of being triggered by high water marks in the heap. Happens all over the place, but most likely when a thread is being killed or when a binder communication is taken down.

There are a few others as well:

GC_CONCURRENT Triggered when the heap has reached a certain amount of objects to collect.

GC_EXTERNAL_ALLOC means that the the VM is trying to reduce the amount of memory used for collectable objects, to make room for more non-collectable.

typedefenum{ 
   
/* Not enough space for an "ordinary" Object to be allocated. */ 
    GC_FOR_MALLOC
, 
   
/* Automatic GC triggered by exceeding a heap occupancy threshold. */ 
    GC_CONCURRENT
, 
   
/* Explicit GC via Runtime.gc(), VMRuntime.gc(), or SIGUSR1. */ 
    GC_EXPLICIT
, 
   
/* GC to try to reduce heap footprint to allow more non-GC'ed memory. */ 
    GC_EXTERNAL_ALLOC
, 
   
/* GC to dump heap contents to a file, only used under WITH_HPROF */ 
    GC_HPROF_DUMP_HEAP 
}GcReason; 

 

GC_EXTERNAL_ALLOC freed 297K, 49% free 3411K/6663K, external 24870K/26260K, paused 83ms
这里边的每个数字都是什么意思阿?
free 3411K/6663K和external 24870K/26260K,分别都是表示什么的阿?

 释放了297K,现在Free的内存是49%,已用的内存是3411,总得内存是6663

自问自答:

前面Free的内存是VM中java使用的内存,external是指VM中通过JNI中Native的类中的malloc分配出的内存,例如Bitmap和一些Cursor都是这么分配的。
在Davilk中,给一个程序分配的内存根据机型厂商的不同,而不同,现在的大部分的是32M了,而在VM内部会把这些内存分成java使用的内存和 Native使用的内存,它们之间是不能共享的,就是说当你的Native内存用完了,现在Java又有空闲的内存,这时Native会重新像VM申请,而不是直接使用java的。
例如上边的例子
free 3411K/6663K和external 24870K/26260K
如果这时需要创建一个2M的Bitmap,Native现有内存26260-24870=1390K<2048k,因此他就会向Vm申请内存,虽然java空闲的内存是
6663-3411=3252>2048,但这部分内存Native是不能使用。
但是你现在去申请2M的Native内存,VM会告诉你无法分配的,因为现在已使用的内存已经接近峰值了32M(26260+6663=32923 ),所以现在就会成force close 报OOM
所以现在我们要检查我们的native内存的使用情况来避免OOM。

 

总结:通过Heap可以查看到Java使用内存情况,但是无法查看JNI使用内存的情况,所以遇到内存溢出时,项目要是调用到动态库的,就留意一下通过JNI申请的内存是否合理释放。

从什么地方可以看出每个应用程序最大的可以用内存是32M

答案:可以使用命令 adb shell dumpsys meminfo com.bb 或者当内存溢出时 Out of memory: Heap Size=8263KB, Allocated=3812KB, Bitmap Size=14235KB,Limit=32768KB

Limit=32768KB便是最大可用内存

但是不同的手机,似乎最大内存限制不一样,下面是我的小手机查出的limit==20480.,不清楚是不是由于系统不完全一样的原因(小手机是2.3.3),还是由手机厂商控制的

                    native   dalvik    other    total    limit   bitmap nativeBm
p
            size:     7136     6759      N/A    13895    20480      N/A      N/A

 

解释 :Out of memory: Heap Size=19783KB, Allocated=17291KB, Bitmap Size=734KB, Limit=20480KB

Heap Size=19783KB 是堆大小

Bitmap Size=734KB 图片大小

Allocated=17291KB 不知道什么意思

Limit=20480KB 最大上限

当 Heap Size + Bitmap Size > Limit 就会OOM


 

======================================= 内存分配======================================
Debug.MemoryInfo[] memoryInfo中参数的意思

dalvikPrivateDirty: The private dirty pages used by dalvik。
dalvikPss :The proportional set size for dalvik.
dalvikSharedDirty :The shared dirty pages used by dalvik.
nativePrivateDirty :The private dirty pages used by the native heap.
nativePss :The proportional set size for the native heap.
nativeSharedDirty :The shared dirty pages used by the native heap.
otherPrivateDirty :The private dirty pages used by everything else.
otherPss :The proportional set size for everything else.
otherSharedDirty :The shared dirty pages used by everything else.

 Android和Linux一样有大量内存在进程之间进程共享。某个进程准确的使用好多内存实际上是很难统计的。
因为有paging out to disk(换页),所以如果你把所有映射到进程的内存相加,它可能大于你的内存的实际物理大小。

        dalvik:是指dalvik所使用的内存。
        native:是被native堆使用的内存。应该指使用C\C++在堆上分配的内存。
        other:是指除dalvik和native使用的内存。但是具体是指什么呢?至少包括在C\C++分配的非堆内存,比如分配在栈上的内存。puzlle!
       private:是指私有的。非共享的。
       share:是指共享的内存。
       PSS:实际使用的物理内存(比例分配共享库占用的内存)
       Pss:它是把共享内存根据一定比例分摊到共享它的各个进程来计算所得到进程使用内存。网上又说是比例分配共享库占用的内存,那么至于这里的共享是否只是库的共享,还是不清楚。
       PrivateDirty:它是指非共享的,又不能换页出去(can not be paged to disk )的内存的大小。比如Linux为了提高分配内存速度而缓冲的小对象,即使你的进程结束,该内存也不会释放掉,它只是又重新回到缓冲中而已。
       SharedDirty:参照PrivateDirty我认为它应该是指共享的,又不能换页出去(can not be paged to disk )的内存的大小。比如Linux为了提高分配内存速度而缓冲的小对象,即使所有共享它的进程结束,该内存也不会释放掉,它只是又重新回到缓冲中而已

======================== 如何用命令查看内存================

http://blog.csdn.net/vincew/article/details/6836319

http://stackoverflow.com/questions/2298208/how-to-discover-memory-usage-of-my-application-in-android#2299813

  用以下命令可以查看程序的内存使用情况:

adb shell dumpsys meminfo $package_name or $pid   //使用程序的包名或者进程id

      用android自带的launcher程序为例:

01

run: adb shell dumpsys meminfo com.android.launcher

命令二 "adb shell cat /proc/meminfo 参考http://blog.csdn.net/kieven2008/article/details/6445421

意思是直接对Android文件进行解析查询,
/proc/cpuinfo系统CPU的类型等多种信息。
/proc/meminfo 系统内存使用信息

/proc/meminfo
MemTotal: 16344972 kB
MemFree: 13634064 kB
Buffers: 3656 kB
Cached: 1195708 kB
我们查看机器内存时,会发现MemFree的值很小。这主要是因为,在linux中有这么一种思想,内存不用白不用,因此它尽可能的cache和buffer一些数据,以方便下次使用。但实际上这些内存也是可以立刻拿来使用的。
所以 空闲内存=free+buffers+cached=total-used
通过读取文件/proc/meminfo的信息获取Memory的总量。
ActivityManager. getMemoryInfo(ActivityManager.MemoryInfo)获取当前的可用Memory量。

命令三:adb shell procrank

If you just want to look at memory usage across all processes, you can use the command "adb shell procrank". Output of this on the same 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

内存耗用:VSS/RSS/PSS/USS
Terms
• VSS - Virtual Set Size 虚拟耗用内存(包含共享库占用的内存)
• RSS - Resident Set Size 实际使用物理内存(包含共享库占用的内存)
• PSS - Proportional Set Size 实际使用的物理内存(比例分配共享库占用的内存)
• USS - Unique Set Size 进程独自占用的物理内存(不包含共享库占用的内存)
一般来说内存占用大小有如下规律:VSS >= RSS >= PSS >= USS
USS is the total private memory for a process, i.e. that memory that is completely unique to that process.USS is an extremely useful number because it indicates the true incremental cost of running a particular process. When a process is killed, the USS is the total memory that is actually returned to the system. USS is the best number to watch when initially suspicious of memory leaks in a process.

============================避免内存溢出的其他事项==============

http://wenku.baidu.com/view/6bca3f6b25c52cc58bd6bebf.html

原创粉丝点击