Java自动内存管理二
在这篇精彩的帖子http://www.nowcoder.com/discuss/3782里详细的介绍了JVM在运行时内存的分布,对象如何创建和布局以及查找对象方式,这些基本知识是了解Java内存如何完成自动管理的基础。然后这些只是内存自动管理的一部分,也即java对象的创建;下面我再仔细的说下java对象如何在内存中分配的和java对象是如何回收的呢?这就是著名的垃圾回收机制啦! 总的来说,整个垃圾回收情况可以用3个简单的英语单词来说明白的:where,when和how。相信如果读过我上篇帖子的人,会明白where这个单词的含义了,这里不在详细说了。下面来谈下when这个单词:对象何时需要被回收的?也就是何时回收无效对象,已死对象的?这里涉及到两种做法的。 引用计数法,也是大家最常见听到的说法,当然面试的时候,大家也最喜欢说出这个答案了,但是考官会觉得远远不够的。然而我们学习的时候,还是要了解的。该算法原理是:为每个对象添加一个计数器,当对象被引用时,计数器值加1;当对象引用失效时,计数器值减1;如果在任意时刻对象的计数器值为0,说明对象已经死了。初看起来,原理很简单。然而在实际的虚拟机上不会使用该算的,eg HotSpot虚拟机。其最大的缺点是无法解决循环引用的问题。何为循环引用呢?对象A引用了对象B,对象B反过来引用了对象A,这样两个对象无法按照引用计数法来判定其死亡状态。 另一种做法是采用可达性分析算法。取一系列Roots点作为搜索路径的起点,向下搜索对象,把搜索路径称为引用链,如果Roots到对象不存在任何的引用链,那就说明此对象已经死亡了的。这里还涉及到java中4种引用方式:强引用,软引用,弱引用和虚引用,其引用强度越来越来低,意味着引用越弱的对象越容易被垃圾回收的。 另外还需要特别注意的是java对象的死亡判断不是一次就可以的,它还涉及到二次的判断。这二次判断关键在于对象是否复写了finalize()方法;如果对象复写了此方法,而且对象还没执行过此方法,此时在上次已判断死亡的对象会进行二次判断,当然在二次判断中,对象可能会逃逸死亡的危险哦!是不是很神奇的。到这里when这个词就介绍完了。下面介绍how这个单词。 how:对象如何被回收的?JVM常采用了4种做法。第一,标记-清除法。原理是:分为两步;标记:按照可达性分析法和二次判断完成死亡标记;清除:把所有标记对象都清除的。这种做法缺点有:在时间上效率不高;在空间上带来不连续问题。下面的3种方法都是对这二个问题的改进。 第二、复制算法。把内存分布两部分,在一部分完成对象的创建,按照上述讲的方法判断对象死亡状态,然后把存活对象复制到空内存内,把另一部分内存对象全部清除;这种做法空间浪费很严重,但在实际中(HotSpot)采用的是把内存分为一个Eden和两个Survivor空间,其中Eden:Survivor=8:1;把Eden和其中一个Survivor作为新建对象内存空间; 第三,标记-整理。标记跟前面一样,整理:把对象都想向一端移动,然后清楚在边界之外的对象。 第四,分代收集算法。新生代采用复制算法;老年代采用标记-整理算法。 下面再讲讲实际中垃圾收集器的种类。这里可以分代来看的;新生代:Serial收集器,单线程的;parNew收集器:多线程收集器;parallel scanage收集器;老年代:Serial old也是单线程收集的;parallel old:多线程收集器;CMS:以提高效率的收集器。最后一种是最新的收集器G1. 到这里,java的内存自动管理就差不多讲完了的。希望大家能够明白其中的原理,共同学习进步!
#阿里巴巴##安卓工程师#