Android gc垃圾回收研究学习

转载 2015年11月19日 19:46:27

欢迎大家访问我的博客http://blog.csdn.net/mikejaps专注于android ios  app 开发

尊重个人劳动成果,转载请注明出处:http://blog.csdn.net/hnulwt/article/details/44903331 
文中很多内容说到了JVM,我想通过研究学习JVM来达到认识DVM的目的。为了严谨,查询了一下

JVM和DVM的不同点

1、Dalvik 和标准 Java 虚拟机(JVM)的首要差别

Dalvik 基于寄存器,而 JVM 基于栈。基于寄存器的虚拟机对于更大的程序来说,在它们编译的时候,花费的时间更短。

2、Dalvik 和 Java 字节码的区别

Dalvik执行.dex格式的字节码,而JVM执行.class格式的字节码。android程序编译完之后生产.class文件,还有通过aapt工具生成的R.class等,然后dx工具会把.class文件处理成.dex文件,最终资源文件和.dex文件等打包成.apk文件。

3、Dalvik和Java运行环境的区别

Dalvik主要是完成对象生命周期管理,堆栈管理,线程管理,安全和异常管理,以及垃圾回收等等重要功能。 
Dalvik负责进程隔离和线程管理,每一个Android应用在底层都会对应一个独立的Dalvik虚拟机实例,其代码在虚拟机的解释下得以执行。

通过以上可以看出,这些不同点并不影响对DVM—gc相关的学习,所以我通过研究JVM相关的垃圾回收机制,来学习Android gc相关内容,如果文中有什么不对的地方,麻烦大家指出,共同学习,共同进步。

粗略的说:GC(Garbage Collection)动态回收无任何引用的对象占据的内存空间。GC通过确定对象是否被活动对象引用来确定是否收集该对象。 
但是理解以上几句话我们可能需要了解以下知识。

JVM内存模型

这里写图片描述

Young Generation

图中的Eden + S0 + S1 
Eden:存放新生的对象 
Survivor Space:S0、S1 有两个,存放每次垃圾回收后存活的对象 
(1)大多数新建的对象都位于Eden区。 
(2)当Eden区被对象填满时,就会执行Minor GC。并把所有存活下来的对象转移到其中一个survivor区。 
(3)Minor GC同样会检查存活下来的对象,并把它们转移到另一个survivor区。这样在一段时间内,总会有一个空的survivor区。

Old Generation

图中的Old Memory 主要存放应用程序中 长期存活的对象和经过多次Minor GC后依然存活下来的对象。通常会在老年代内存被占满时进行垃圾回收。老年代的垃圾收集叫做Major GC。Major GC会花费更多的时间。

Permanent Generation:

存放方法区,方法区中有 要加载的类信息、静态变量、final类型的常量、属性和方法信息。

JVM分别对新生代和旧生代采用的两种垃圾回收机制?

新生代的GC:

新生代通常存活时间较短,因此基于Copying算法来进行回收,所谓Copying算法就是扫描出存活的对象,并复制到一块新的完全未使用的空间中,对应于新生代,就是在Eden和FromSpace或ToSpace之间copy。新生代采用空闲指针的方式来控制GC触发,指针保持最后一个分配的对象在新生代区间的位置,当有新的对象要分配内存时,用于检查空间是否足够,不够就触发GC。当连续分配对象时,对象会逐渐从eden到survivor,最后到旧生代。

旧生代的GC:

旧生代与新生代不同,对象存活的时间比较长,比较稳定,因此采用标记(Mark)算法来进行回收,所谓标记就是扫描出存活的对象,然后再进行回收未被标记的对象,回收后对用空出的空间要么进行合并,要么标记出来便于下次进行分配,总之就是要减少内存碎片带来的效率损耗。

如何判断对象是否可以被回收?

两种常用的方法是引用计数和对象引用遍历。

(1)引用计数收集器

引用计数是垃圾收集器中的早期策略。在这种方法中,堆中每个对象(不是引用)都有一个引用计数。当一个对象被创建时,且将该对象分配给一个变量,该变量计数设置为1。当任何其它变量被赋值为这个对象的引用时,计数加1(a = b,则b引用的对象+1),但当一个对象的某个引用超过了生命周期或者被设置为一个新值时,对象的引用计数减1。任何引用计数为0的对象可以被当作垃圾收集。当一个对象被垃圾收集时,它引用的任何对象计数减1。

优点:引用计数收集器可以很快的执行,交织在程序运行中。对程序不被长时间打断的实时环境比较有利。

缺点: 无法检测出循环引用。如父对象有一个对子对象的引用,子对象反过来引用父对象。这样,他们的引用计数永远不可能为0.

(2)跟踪收集器

现在大多数JVM采用对象引用遍历。对象引用遍历从一组对象开始,沿着整个对象图上的每条链接,递归确定可到达(reachable)的对象。如果某对象不能从这些根对象的一个(至少一个)到达,则将它作为垃圾收集。在对象遍历阶段,GC必须记住哪些对象可以到达,以便删除不可到达的对象,这称为标记(marking)对象。

下一步,GC要删除不可到达的对象。删除时,有些GC只是简单的扫描堆栈,删除未标记的未标记的对象,并释放它们的内存以生成新的对象,这叫做清除(sweeping)。这种方法的问题在于内存会分成好多小段,而它们不足以用于新的对象,但是组合起来却很大。因此,许多GC可以重新组织内存中的对象,并进行压缩(compact),形成可利用的空间。

为此,GC需要停止其他的活动活动。这种方法意味着所有与应用程序相关的工作停止,只有GC运行。结果,在响应期间增减了许多混杂请求。另外,更复杂的 GC不断增加或同时运行以减少或者清除应用程序的中断。有的GC使用单线程完成这项工作,有的则采用多线程以增加效率。

gc的原因(Log释义)

在官方文档上查了一下,gc reason有如下5个:

<code class="hljs applescript has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;">GC_CONCURRENT
A concurrent garbage collection <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">that</span> frees up memory <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">as</span> your heap begins <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">to</span> fill up.
GC_FOR_MALLOC
A garbage collection caused because your app attempted <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">to</span> allocate memory when your heap was already full, so <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">the</span> system had <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">to</span> stop your app <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">and</span> reclaim memory.
GC_HPROF_DUMP_HEAP
A garbage collection <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">that</span> occurs when you create an HPROF <span class="hljs-type" style="box-sizing: border-box;">file</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">to</span> analyze your heap.
GC_EXPLICIT
An explicit garbage collection, such <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">as</span> when you call gc() (which you should avoid calling <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">and</span> instead trust <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">the</span> garbage collector <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">to</span> <span class="hljs-command" style="box-sizing: border-box;">run</span> when needed).
GC_EXTERNAL_ALLOC
This happens only <span class="hljs-function_start" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">on</span></span> API level <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">10</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">and</span> lower (newer versions allocate everything <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">in</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">the</span> Dalvik heap). A garbage collection <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> externally allocated memory (such <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">as</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">the</span> pixel data stored <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">in</span> native memory <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">or</span> NIO byte buffers).</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li></ul>

GC_CONCURRENT、GC_FOR_MALLOC都是比较常见的gc原因。可以通过运行程序在Logcat上查看。 
GC_CONCURRENT当堆要满的时候进行的垃圾收集 
GC_FOR_MALLOC这就是“Stop the World”事件,因为所有的应用线程都会停下来直到操作完成。这时候堆已经满了,你申请分配内存就会触发这种原因的gc。

GC_HPROF_DUMP_HEAP 
在我们创建HPROF文件分析堆内存的时候的gc原因。

GC_EXPLICIT 
当我们显示的调用System.gc()方法,会出现的log。

GC_EXTERNAL_ALLOC 
这个仅仅在API 10 及以下才会出现,我们不需要关注了。

文章部分参考自: 
原文链接: journaldev 翻译: ImportNew.com - 进林 译文链接: http://www.importnew.com/14086.html 
详细介绍Java垃圾回收机制:http://www.cnblogs.com/laoyangHJ/articles/java_gc.html 
百度百科:http://baike.baidu.com/view/1551869.htm

Android gc垃圾回收研究学习

JVM内存模型 JVM分别对新生代和旧生代采用的两种垃圾回收机制 如何判断对象是否可以被回收 gc的原因(Log释义)...
  • hnulwt
  • hnulwt
  • 2015年04月09日 09:22
  • 6325

Android gc垃圾回收研究学习

尊重个人劳动成果,转载请注明出处:http://blog.csdn.net/hnulwt/article/details/44903331 文中很多内容说到了JVM,我想通过研究学习JVM来达到认...

Android内存使用——垃圾回收LOG,GC_CONCURRENT等的意义的说明(有用)

在调试程序的时候,经常发现GC_CONCURRENT之类的打印。在网上搜了一下,感觉说法各式各样。最后,在Google的官方网站上发现了详细介绍。 Every time a garbage co...

Android 内存 - 垃圾回收(GC)机制

虽然Java大部分内存由垃圾回收器(GC)管理着,但是对内存的释放还是有必要知道一点的,毕竟对我们编程也是有一定的帮助的。例如,解决内存泄露问题等等!!GC回收哪个区域的垃圾这里所说的区域指的是运行时...

Android内存使用——垃圾回收LOG,GC_CONCURRENT等的意义的说明

在调试程序的时候,经常发现GC_CONCURRENT之类的打印。在网上搜了一下,感觉说法各式各样。最后,在Google的官方网站上发现了详细介绍。 Every time a garbage coll...

Android GC 垃圾回收详解

1. 垃圾回收的意义   在C++中,对象所占的内存在程序结束运行之前一直被占用,在明确释放之前不能分配给其它对象;而在Java中,当没有对象引用指向原先分配给某个对象的内存时,该内存便成为垃圾。JV...

.NET_C#_栈_堆_垃圾回收GC

  • 2013年01月10日 11:19
  • 528KB
  • 下载

Java_GC垃圾回收调优指南

  • 2011年04月25日 16:04
  • 285KB
  • 下载

Java学习笔记--垃圾回收GC

一,概述1, 从java内存区域说起 java内存区域通常划分为这么几块: (1) java堆: 对象及数组引用 (2) 虚拟机栈: 局部变量等 (3) 方法区: 类相关信息,常量、静态变量等...

JVM学习笔记二:GC 垃圾回收

概述学过一点java的都知道,java的GC是有JVM自动执行的。java内存运行时区域的各个部分,其中程序计数器、栈(虚拟机栈、本地方法栈)这些区域随着线程而生随线程灭而亡,这些区域内存分配和回收都...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Android gc垃圾回收研究学习
举报原因:
原因补充:

(最多只允许输入30个字)