相关文章
Android内存优化系列
Java虚拟机系列
前言
在Java虚拟机(三)垃圾标记算法与Java对象的生命周期这篇文章中,提到了Java虚拟机的GC日志。DVM和ART的GC日志与Java虚拟机的日志有较大的区别,这篇文章就对DVM和ART的GC日志进行分析。
1.DVM的GC日志
在 DVM 中,每次垃圾收集都会将GC日志打印到 logcat 中,具体的格式为:
D/dalvikvm: <GC_Reason> <Amount_freed>, <Heap_stats>, <External_memory_stats>, <Pause_time>
可以看到DVM的日志共有5个信息,其中GC Reason有很多种,这里将它单独拿出来进行介绍。
引起GC原因
GC Reason就是指引起GC原因,有以下几种:
- GC_CONCURRENT:当堆开始填充时,并发GC可以释放内存。
- GC_FOR_MALLOC:当堆内存已满时,app尝试分配内存而引起的GC,系统必须停止app并回收内存。
- GC_HPROF_DUMP_HEAP:当你请求创建 HPROF 文件来分析堆内存时出现的GC。
- GC_EXPLICIT:显示的GC,例如调用System.gc()(应该避免调用显示的GC,信任GC会在需要时运行)。
- GC_EXTERNAL_ALLOC:仅适用于 API 级别小于等于10 ,用于外部分配内存的GC。
其他信息
除了引起GC原因,其他的信息为:
- Amount_freed:本次GC释放内存的大小。
- Heap_stats:堆的空闲内存百分比 (已用内存)/(堆的总内存)。
- External_memory_stats:API 级别 10 及更低级别的内存分配 (已分配的内存)/(引起GC的阀值)。
- Pause time:暂停时间,更大的堆会有更长的暂停时间。并发暂停时间显示了两个暂停:一个出现在垃圾收集开始时,另一个出现在垃圾收集快要完成时。
实例分析
D/dalvikvm: GC_CONCURRENT freed 2012K, 63% free 3213K/9291K, external 4501K/5161K, paused 2ms+2ms
这个GC日志的含义为:引起GC的原因是GC_CONCURRENT;本次GC释放的内存为2012K;堆的空闲内存百分比为63%,已用内存为3213K,堆的总内存为9291K;暂停的总时长为4ms。
2.ART的GC日志
ART的GC日志与DVM不同,ART 不会为没有明确请求的垃圾收集打印GC日志。只有在认为GC速度慢时才会打印GC日志,更确切来说,仅在GC暂停超过5ms 或GC持续时间超过 100ms 时才会打印GC日志。如果app未处于可察觉的暂停进程状态,那么它的GC不会被认为是慢速的。ART的GC日志始终会记录显式的垃圾收集。
ART的GC日志具体的格式为:
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原因
ART的引起GC原因(GC_Reason)要比DVM多一些,有以下几种:
- Concurrent: 并发GC,不会使App的线程暂停,该GC是在后台线程运行的,并不会阻止内存分配。
- Alloc:当堆内存已满时,App尝试分配内存而引起的GC,这个GC会发生在正在分配内存的线程。
- Explicit:App显示的请求垃圾收集,例如调用System.gc()。与DVM一样,最佳做法是应该信任GC并避免显示的请求GC,显示的请求GC会阻止分配线程并不必要的浪费 CPU 周期。如果显式的请求GC导致其他线程被抢占,那么有可能会导致 jank(App同一帧画了多次)。
- NativeAlloc:Native内存分配时,比如为Bitmaps或者RenderScript分配对象, 这会导致Native内存压力,从而触发GC。
- CollectorTransition:由堆转换引起的回收,这是运行时切换GC而引起的。收集器转换包括将所有对象从空闲列表空间复制到碰撞指针空间(反之亦然)。当前,收集器转换仅在以下情况下出现:在内存较小的设备上,App将进程状态从可察觉的暂停状态变更为可察觉的非暂停状态(反之亦然)。
- HomogeneousSpaceCompact:齐性空间压缩是指空闲列表到压缩的空闲列表空间,通常发生在当App已经移动到可察觉的暂停进程状态。这样做的主要原因是减少了内存使用并对堆内存进行碎片整理。
- DisableMovingGc:不是真正的触发GC原因,发生并发堆压缩时,由于使用了 GetPrimitiveArrayCritical,收集会被阻塞。一般情况下,强烈建议不要使用 GetPrimitiveArrayCritical,因为它在移动收集器方面具有限制。
- HeapTrim:不是触发GC原因,但是请注意,收集会一直被阻塞,直到堆内存整理完毕。
垃圾收集器名称
GC_Name指的是垃圾收集器名称,有以下几种:
- Concurrent mark sweep (CMS):CMS收集器是一种以获取最短收集暂停时间为目标收集器,采用了标记-清除算法(Mark-Sweep)实现。 它是完整的堆垃圾收集器,能释放除了Image Space之外的所有的空间。
- Concurrent partial mark sweep:部分完整的堆垃圾收集器,能释放除了Image Space和Zygote Spaces之外的所有空间。关于Image Space和Zygote Spaces可以查看Android内存优化(一)DVM和ART原理初探这篇文章。
- Concurrent sticky mark sweep:分代收集器,它只能释放自上次GC以来分配的对象。这个垃圾收集器比一个完整的或部分完整的垃圾收集器扫描的更频繁,因为它更快并且有更短的暂停时间。
- Marksweep + semispace:非并发的GC,复制GC用于堆转换以及齐性空间压缩(堆碎片整理)。
其他信息
- Objects freed:本次GC从非Large Object Space中回收的对象的数量。
- Size_freed:本次GC从非Large Object Space中回收的字节数。
- Large objects freed: 本次GC从Large Object Space中回收的对象的数量。
- Large object size freed:本次GC从Large Object Space中回收的字节数。
- Heap stats:堆的空闲内存百分比 (已用内存)/(堆的总内存)。
- Pause times:暂停时间,暂停时间与在GC运行时修改的对象引用的数量成比例。目前,ART的CMS收集器仅有一次暂停,它出现GC的结尾附近。移动的垃圾收集器暂停时间会很长,会在大部分垃圾回收期间持续出现。
实例分析
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
这个GC日志的含义为:引起GC原因是Explicit ;垃圾收集器为CMS收集器;释放对象的数量为104710个,释放字节数为7MB;释放大对象的数量为21个,释放大对象字节数为416KB;堆的空闲内存百分比为33%,已用内存为25MB,堆的总内存为38MB;GC暂停时长为1.230ms,GC总时长为67.216ms。
参考资料
Investigating Your RAM Usage
欢迎关注我的微信公众号,第一时间获得博客更新提醒,以及更多成体系的Android相关原创技术干货。
扫一扫下方二维码或者长按识别二维码,即可关注。
Android内存优化(二)DVM和ART的GC日志分析的更多相关文章
-
Android内存优化(一)DVM和ART原理初探
相关文章 Android内存优化系列 Java虚拟机系列 前言 要学习Android的内存优化,首先要了解Java虚拟机,此前我用了多篇文章来介绍Java虚拟机的知识,就是为了这个系列做铺垫.在And ...
-
Android内存优化(三)详解内存分析工具MAT
前言 在这个系列的前四篇文章中,我分别介绍了DVM.ART.内存泄漏和内存检测工具的相关知识点,这一篇我们通过一个小例子,来学习如何使用内存分析工具MAT. 1.概述 在进行内存分析时,我们可以使用M ...
-
【腾讯Bugly干货分享】Android内存优化总结&;实践
本文来自于腾讯Bugly公众号(weixinBugly),未经作者同意,请勿转载,原文地址:https://mp.weixin.qq.com/s/2MsEAR9pQfMr1Sfs7cPdWQ 导语 智 ...
-
Android内存优化杂谈
Android内存优化是我们性能优化工作中比较重要的一环,这里其实主要包括两方面的工作: 优化RAM,即降低运行时内存.这里的目的是防止程序发生OOM异常,以及降低程序由于内存过大被LMK机制杀死的概 ...
-
[转]探索 Android 内存优化方法
前言 这篇文章的内容是我回顾和再学习 Android 内存优化的过程中整理出来的,整理的目的是让我自己对 Android 内存优化相关知识的认识更全面一些,分享的目的是希望大家也能从这些知识中得到一些 ...
-
大礼包!ANDROID内存优化(大汇总)
写在最前: 本文的思路主要借鉴了2014年AnDevCon开发者大会的一个演讲PPT,加上把网上搜集的各种内存零散知识点进行汇总.挑选.简化后整理而成. 所以我将本文定义为一个工具类的文章,如果你在A ...
-
ANDROID内存优化——大汇总(转)
原文作者博客:转载请注明本文出自大苞米的博客(http://blog.csdn.net/a396901990),谢谢支持! ANDROID内存优化(大汇总——上) 写在最前: 本文的思路主要借鉴了20 ...
-
Android内存优化1 了解java内存分配 1
开篇废话 今天我们一起来学习JVM的内存分配,主要目的是为我们Android内存优化打下基础. 一直在想以什么样的方式来呈现这个知识点才能让我们易于理解,最终决定使用方法为:图解+源代码分析. 欢迎访 ...
-
ANDROID内存优化(大汇总——全)
写在最前: 本文的思路主要借鉴了2014年AnDevCon开发者大会的一个演讲PPT,加上把网上搜集的各种内存零散知识点进行汇总.挑选.简化后整理而成. 所以我将本文定义为一个工具类的文章,如果你在A ...
随机推荐
-
OAuth2学习及DotNetOpenAuth部分源码研究
OAuth2学习及DotNetOpenAuth部分源码研究 在上篇文章中我研究了OpenId及DotNetOpenAuth的相关应用,这一篇继续研究OAuth2. 一.什么是OAuth2 OAuth是 ...
-
C#常用集合的使用(转载)
大多数集合都在System.Collections,System.Collections.Generic两个命名空间.其中System.Collections.Generic专门用于泛型集合. 针对特 ...
-
Codeforces Round #190 DIV.2 A. Ciel and Dancing
#include <cstdio> #include <iostream> #include <vector> using namespace std; int m ...
-
C# Wpf异步修改UI,多线程修改UI(二)
1.使用定时器异步修改 这是相对比较简单的方法 在Wpf中定时器使用DiapatcherTimer,不使用Timer原因: 在一个应用程序中,Timer会重复生成time事件,而DispatcherT ...
-
ASP.net获取当前页面的文件名,参数,域名等方法
ASP.net后台获取当前页面的文件名 System.IO.Path.GetFileName(Request.Path).ToString(); 获取当前页面文件名,参数,域名等方法 假设当前页完整地 ...
-
ORA-19573: cannot obtain exclusive enqueue for datafile 1
还原Oracle数据库时出现ORA-19870和ORA-19573错误,如: RMAN> restore database; Starting restore at 11-DEC-12 usin ...
-
(转)IE劫持原理 BHO
为什么“浏览器劫持”能够如此猖狂呢?放眼众多论坛的求助贴,我们不时可以看到诸如“我的IE被主页被改了,我用杀毒工具扫了一遍都没发现病毒,我把主页改回自己的地址,可是一重启它又回来了!”.“我的系统一开 ...
-
Java基础系列--02_运算符和程序的语句
运算符: (1)算术运算符: +,-,*,/,%,++,--(加.减.乘.除.取余.自增,自减) ++和--的注意事项: a:他们的作用是自增或者自减 b:使用 1.单独使用 放在操作数据的前面和后面 ...
-
Opencv-Python学习笔记(一)
学习和研究计算机视觉,必然绕不开OpenCV. 于是我下载了它的C++源码,用cmake编译遇到一些错误. 然后结合网上一些帖子看源码看了好几天,发现有点不知从何处入手. 于是准备从其python版本 ...
-
WebApi XML,Json格式自定义,IEnumerable<;T>;,ArrayOf
global.ascx中application-start() GlobalConfiguration.Configuration.Formatters.XmlFormatter.UseXmlSeri ...