Android gc垃圾回收研究学习

尊重个人劳动成果,转载请注明出处: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个:

GC_CONCURRENT
A concurrent garbage collection that frees up memory as your heap begins to fill up.
GC_FOR_MALLOC
A garbage collection caused because your app attempted to allocate memory when your heap was already full, so the system had to stop your app and reclaim memory.
GC_HPROF_DUMP_HEAP
A garbage collection that occurs when you create an HPROF file to analyze your heap.
GC_EXPLICIT
An explicit garbage collection, such as when you call gc() (which you should avoid calling and instead trust the garbage collector to run when needed).
GC_EXTERNAL_ALLOC
This happens only on API level 10 and lower (newer versions allocate everything in the Dalvik heap). A garbage collection for externally allocated memory (such as the pixel data stored in native memory or NIO byte buffers).
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

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

时间: 2024-09-25 02:35:30

Android gc垃圾回收研究学习的相关文章

简析Android的垃圾回收与内存泄露

Android系统是运行在Java虚拟机上的,作为嵌入式设备,内存往往非常有限,了解Android的垃圾回收机制,可以有效的防止内存泄露问题或者OOM问题.本文作为入门文章,将浅显的讨论垃圾回收与内存泄露的原理,不讨论Dalvik虚拟机底层机制或者native层面的问题. 1. 基础 在分析垃圾回收前,我们要复习Java与离散数学的基础. 实例化:对象是类的一个实例,创建对象的过程也叫类的实例化.对象是以类为模板来创建的.比如Car car = new Car();,我们就创造了一个Car的实例

GC垃圾回收算法

什么是GC垃圾回收呢.日常生活中我们去餐厅吃饭吃完饭,吃完饭走了餐具不用管,服务员在把餐具拿走,这是一种方式,服务员怎么知道他要来把餐具拿走呢,因为你走了,这个位置空了.服务员什么时候拿走餐具很重要,第一你没吃完,不会回收吧,第二很多人吃饭,你在里面,他也不一定回收吧,他会找一个合适的时机,一次性回收很多吧. 第二种方法:自己吃完饭把餐具带到回收的地方吧. 哪一种方式更好呢? 第一种方式自己也就是使用者不用管,服务员找一个合适的时机把垃圾回收了. 第二种自己去吧垃圾倒了. 在java中GC垃圾回

从JVM的内存管理角度分析Java的GC垃圾回收机制_java

一个优秀的Java程序员必须了解GC的工作原理.如何优化GC的性能.如何与GC进行有限的交互,因为有一些应用程序对性能要求较高,例如嵌入式系统.实时系统等,只有全面提升内存的管理效率 ,才能提高整个应用程序的性能.本篇文章首先简单介绍GC的工作原理之后,然后再对GC的几个关键问题进行深入探讨,最后提出一些Java程序设计建议,从GC角度提高Java程序的性能.    GC的基本原理    Java的内存管理实际上就是对象的管理,其中包括对象的分配和释放.     对于程序员来说,分配对象使用ne

Android垃圾回收机制解决内存泄露问题_Android

在android编码中,会有一些简便的写法和编码习惯,会导致我们的代码有很多内存泄露的问题,在这里做一个已知错误的总结:1.编写单例的时候常出现的错误. 错误方式: public class Foo{ private static Foo foo; private Context mContext; private Foo(Context mContext){ this.mContext = mContext; } // 普通单例,非线程安全 public static Foo getInsta

Android垃圾回收机制解决内存泄露问题

在android编码中,会有一些简便的写法和编码习惯,会导致我们的代码有很多内存泄露的问题,在这里做一个已知错误的总结: 1.编写单例的时候常出现的错误. 错误方式: public class Foo{ private static Foo foo; private Context mContext; private Foo(Context mContext){ this.mContext = mContext; } // 普通单例,非线程安全 public static Foo getInst

Android垃圾回收机制及程序优化System.gc_Android

1.垃圾收集算法的核心思想 Java语言建立了垃圾收集机制,用以跟踪正在使用的对象和发现并回收不再使用(引用)的对象.该机制可以有效防范动态内存分配中可能发生的两个危险:因内存垃圾过多而引发的内存耗尽,以及不恰当的内存释放所造成的内存非法引用. 垃圾收集算法的核心思想是:对虚拟机可用内存空间,即堆空间中的对象进行识别,如果对象正在被引用,那么称其为存活对象,反之,如果对象不再被引用,则为垃圾对象,可以回收其占据的空间,用于再分配.垃圾收集算法的选择和垃圾收集系统参数的合理调节直接影响着系统性能,

对比 Ruby 和 Python 的垃圾回收

注:这篇文章基于我在布达佩斯的RuPy大会上所作的演讲.我觉得与其直接将幻灯片发布出来,不如在我还有印象的时候将它写成博客来的更有意义.同 样,我会在将来发布RuPy大会的视频链接.我计划将在RubyConf大会上发表类似的演讲,除了有关于Python的部分,并且将对比 MRI,JRuby以及Rubinius的垃圾回收器是怎样工作的. 如果想要对Ruby垃圾回收器以及内部原理有更加深入的了解,你可以在我即将出版的新书<Ruby Under a Microscope>中找到答案. 如果算法和业务

.Net 垃圾回收机制详细介绍_实用技巧

析构函数 析构函数不能有修饰符,如public.不能接受任何参数. 编译器自动将一个析构函数转换成对Object.Finalize方法的一个override版,如下. class Test { protected override void Finalize() { try {-} finally { base.Finalize(); } } } 垃圾回收器 .NET垃圾回收器会保证: l  每个对象都会被摧毁,它的析构函数一定会被运行.当一个程序结束后,所有对象都会被销毁. l  每个对象只被

浅析Java中的GC垃圾回收器的意义及与GC的交互_java

对象是使用new创建的,但是并没有与之相对应的delete操作来回收对象占用的内存.当我们完成对某个对象的使用时,只需停止对该对象的引用:将我们的引用改变为指向其他对象或指向null;或者从方法中返回,使得该方法的局部变量不复存在,从而使得对这些局部变量的引用变为不指向任何对象.不再被引用的对象被称为垃圾(garbage),查找并回收这些对象的过程叫做垃圾回收(garbage collection) o Java虚拟机利用垃圾回收来保证被引用的对象将会在内存中保留,同时会释放在执行代码中通过任何