本文翻译自https://developer.android.com/studio/profile/investigate-ram.html,有些话是我自己加的,便于理解,不过我不保证这些话理解错误,欢迎指正。
关于Android手机中的内存重要性就不多说了,应用开发者应该都或多或少被内存的问题折磨过,这个系列文章就把我所知的内存上的一些问题及优化记录下来,给大家一个参考。
Log分为两种:Dalvik和ART
Dalvik的Log
大家在开发过程中,在AS或者Eclipse的lotcat中会看到这样的log:
D/dalvikvm( 9050): GC_CONCURRENT freed 2049K, 65% free 3571K/9991K, external 4703K/5261K, paused 2ms+2ms
一般来说我们不会在意这个log,但是它的确对我们是有一些意义的,我们可以从中看到GC的一些信息
它的组成:
D/dalvikvm: <GC_Reason> <Amount_freed>, <Heap_stats>, <External_memory_stats>, <Pause_time>
我们一个个看->->
GC_Reason
GC的原因,大概有如下几种:
1. GC_CONCURRENT
Heap快满的时候执行的并发GC
2. GC_FOR_MALLOC
程序尝试分配内存,但是Heap已经满了,这时候必须执行GC,另外,因为这时候没法分配内存,所以程序会Stop一会儿,直到内存可以分配,换句话说,这个GC不是并发的
3. GC_HPROF_DUMP_HEAP
这个是我们自己在IDE中点击Dump Heap来创建HPROF文件的时候执行的GC
4. GC_EXPLICIT
显示调用GC
5. GC_EXTERNAL_ALLOC
这个在API10以下才会调用,比如是低版本会有些Bitmap是存在Native内存中的
Amount freed
GC释放的内存数量
Heap stats
Heap内存中的分配情况,Free内存的比例 和 使用的数量/总数量
External memory stats
像上面说的,API10以下才有,额外的内存存储的数量
Pause time
堆内存越大,GC暂停时间越长,一个在GC开始的时候,一个是GC结束的时候,注意这里的暂停时间不是执行时间(具体是什么我猜想大概是会block住主线程的时间)
ART的Log
ART的GC一般来说不会打印出来,只有显示调用GC方法或者系统认为该打印的时候才会打印。
什么是系统认为该打印?就是说,如果GC的暂停时间超过5ms或者GC执行的过程超过100ms,形象点就是GC给我影响有点大了,那么它就自己打印出来告诉开发者。
ART的Log长什么样呢?举个栗子:
I/art : Explicit concurrent mark sweep GC freed 104710(7MB) AllocSpace objects, 21(416KB) LOS objects, 33% free, 25MB/38MB, paused 1.230ms total 67.216ms
格式为:
I/art: <GC_Reason> <GC_Name> <Objects_freed>(<Size_freed>) AllocSpace Objects, <Large_objects_freed>(<Large_object_size_freed>) <Heap_stats> LOS objects, <Pause_time(s)>
同样,它也有GC_Reason,看下具体含义:
1. Concurrent
感觉和上面差不多的意思,就是并发的GC,不会block住主线程,不妨碍程序分配内存
2. Alloc
同样差不多,也是在分配内存的时候内存满了,但是GC的执行在分配内存的那个线程
到这里我大胆猜想一下,Dalvik的Alloc GC是直接Block住整个程序的执行,而这里的GC,如果你是在子线程执行的分配内存操作,那么GC好像也不会影响主线程的执行(如果说错了过来打我,谢谢)。
3. Explicit
同样的,显示调用GC,但是!ART不推荐显示调用GC,因为显示调用GC会Block住分配内存的线程,而且会导致不必要的CPU周期,GC线程也有可能抢占其他应用线程从而导致Jank(这个词的意思大概类似掉帧?)
4. NativeAlloc
Native内存分配时候发生,比如Bitmap和RenderScript创建对象的时候(这段没理解,ART的Bitmap分配在Native内存中的???)
5. CollectorTransition
这段好难理解。可能需要了解一些GC的知识,我这里理解成,GC的时候会从一块内存拷贝一些对象到另一块内存(比如临时内存和存在时间较久的内存),这个过程就是CollectorTransition。另外,目前而言,CollectorTransition只可能发生在低内存的手机,应用从卡顿状态变成不卡顿(反之亦然)的这种情况
6. HomogeneousSpaceCompact
这又是一个GC算法相关的内容,一般发生在App减少内存使用或者碎片整理的时候
7. DisableMovingGc
这个不算是GC的原因,只是告诉我们在使用GetPrimitiveArrayCritical的时候GC Block住了
8. HeapTrim
这个同样不属于GC的原因,只是告诉我们GC因为内存整理Block了
GC_Name
ART中,系统有多种不同类型的GC(不同的算法)
这段实在无能为力,我记得以前看过一篇不错的文章,找不到了,贴一篇老罗的吧:http://blog.csdn.net/luoshengyang/article/details/42072975
Objects_freed/Size_freed
释放的对象数和释放的内存大小
Large_objects_freed/Large_object_size_freed
大的对象释放的数量及内存的大小
Heap stats和Pause times
不多说了
最后说一点,如果你看到你的应用有大量的GC,那么你可以看 Heap stats可以看到总内存和已分配内存,然后看下已分配的内存会不会一直增加,如果是,那么恭喜你,内存泄漏了,另外,如果你看到GC的原因是Alloc,那表明你的内存分配已经很满了,估计会OOM。
写完收工~