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).

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-11-05 11:33:41

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

Java 垃圾回收机制学习

原文链接: http://blog.csdn.net/zsuguangh/article/details/6429592 自己学习总结: 1c++和java的内存使用的区别: 在C++中,对象所占的内存在程序结束运行之前一直被占用,在明确释放之前不能分配给其它对象:而在Java中,当没有对象引用指向原先分配给某个对象的内存时,该内存便成为垃圾. 2: 触发主GC(Garbage Collector)的条件 1)当应用程序空闲时,即没有应用线程在运行时,GC会被调用.因为GC在优先级最低的线程中进

面试官,不要再问我“Java GC垃圾回收机制”了

Java GC垃圾回收几乎是面试必问的JVM问题之一,本篇文章带领大家了解Java GC的底层原理,图文并茂,突破学习及面试瓶颈. 楔子-JVM内存结构补充 在上篇<JVM之内存结构详解>中有些内容我们没有讲,本篇结合垃圾回收机制来一起学习.还记得JVM中堆的结构图吗? 图中展示了堆中三个区域:Eden.From Survivor.To Survivor.从图中可以也可以看到它们的大小比例,准确来说是:8:1:1.为什么要这样设计呢,本篇文章后续会给出解答,还是根据垃圾回收的具体情况来设计的.

数往知来C#之接口 值类型与引用类型 静态非静态 异常处理 GC垃圾回收 值类型引用类型内存分配&lt;四&gt;

C# 基础接口篇 一.多态复习 使用个new来实现,使用virtual与override    -->new隐藏父类方法 根据当前类型,电泳对应的方法(成员)    -->override重写 无论什么情况,都是执行新的方法(成员) 继承是实现多态的一个前提,没有继承多态是不能实现的 父类与子类实现多态 抽象类与子类实现 抽象类不能实例化 抽象类中的抽象方法没有方法体 抽象类的成员有哪些   ->包含非抽象成员   ->不能实例化   ->子类必须实现父类的 抽象方法,除非子

GC 垃圾回收

一.托管 .Net所指的托管资源到底是什么意思呢?是相对于所有资源,还是只限于某一方面的资源?很多人对此不是很了解. 其实.Net所指的托管只是针对内存这一个方面,并不是对于所有的元素:因此对于Stream,数据库的连接GDI+的相关对象,还有Com对象等等,这些资源并不是受到.Net管理而统称为非托管资源.而对于内存的释放和回收,系统提供了GC(Garbage Collector),而至于其他资源则需要手动进行释放. 二.垃圾 什么是垃圾..Net类型分为两大类,一个就是值类型,另一个就是引用

计时器 GC垃圾回收 demo

计时器: 1 public void start() { 2 //定义计时器 3 Timer timer=new Timer(); 4 //定义运行间隔(数字越小,速度越快) 5 int interval=30; 6 //创建定时任务 7 TimerTask task=new TimerTask() { 8 public void run() { 9 moveAction(); //调用的其他方法 10 enemyEnterAction(); 11 repaint(); 12 } 13 }; 1

Android内存优化1 了解java GC 垃圾回收机制3

引言 接App优化之内存优化(序), 作为App优化系列中内存优化的一个小部分. 由于内存相关知识比较生涩, 内存优化中使用到的相关工具, 也有很多专有名词. 对Java内存管理, GC, Android内存管理, Dalvik/ART等知识有一个理论的认识, 可以让我们更好的使用这些工具, 分析内存问题. 据此, 我们就先从理论入手, 聊聊GC那些事儿. 1, 何为GC GC 是 garbage collection 的缩写, 垃圾回收的意思. 也可以是 Garbage Collector,

Java学习之二(线程(了解) JVM GC 垃圾回收)

线程与进程(了解)→JVM→字节码→GC 一.程序 = 算法 + 数据结构(大佬) 二.程序 = 框架 + 业务逻辑(现实) 1.线程与进程.同步与异步 1.1进程是什么? 进程就是操作系统控制的基本运行单元,说白了就是Java运行程序. 1.2什么是线程? 进程中独立运行的子任务就是一个线程 1.3什么是多线程(异步)? 多线程是多个子任务进行交替执行.例如:有A.B两个任务,A先执行,再执行B,如果是单线程执行,则需要等A先执行完之后才能够执行B:而多线程的话是A与B来回交换执行.这样可以让

Android内存优化1 了解java GC 垃圾回收机制2 GC执行finalize的过程

1. finalize的作用 finalize()是Object的protected方法,子类可以覆盖该方法以实现资源清理工作,GC在回收对象之前调用该方法. finalize()与C++中的析构函数不是对应的.C++中的析构函数调用的时机是确定的(对象离开作用域或delete掉),但Java中的finalize的调用具有不确定性 不建议用finalize方法完成"非内存资源"的清理工作,但建议用于:① 清理本地对象(通过JNI创建的对象):② 作为确保某些非内存资源(如Socket.

理解Android Java垃圾回收机制

Jvm(Java虚拟机)内存模型 从Jvm内存模型中入手对于理解GC会有很大的帮助,不过这里只需要了解一个大概,说多了反而混淆视线. Jvm(Java虚拟机)主要管理两种类型内存:堆和非堆.堆是运行时数据区域,所有类实例和数组的内存均从此处分配.非堆是JVM留给自己用的,包含方法区.JVM内部处理或优化所需的内存(如 JIT Compiler,Just-in-time Compiler,即时编译后的代码缓存).每个类结构(如运行时常数池.字段和方法数据)以及方法和构造方法的代码. 简言之,Jav