赞
踩
目录
java技术体系中自动内存管理分为两个问题:
- 给对象分配内存
- 回收给对象分配的内存
内存的分配涉及到的内存区域是:堆区(堆+方法区)
垃圾回收(Garbage Collection)是Java虚拟机(JVM)垃圾回收器提供的一种用于在空闲时间不定时回收无任何对象引用的对象占据的内存空间的一种机制。 (仅仅回收无引用对象所实际占用的空间,对象引用不回收)
作用:有效防止内存泄漏、保证内存的有效使用,解放程序员双手。
堆 (包括Java堆 和 方法区)是 垃圾回收的主要对象,特别是Java堆。
三个核心问题:
接下来便来回答这三个核心问题:
通常有两种方法:
通过判断对象的引用数量来决定对象是否可以被回收。
引用计数算法是垃圾收集器中的早期策略。在对象中添加一个引用计数器,每当有一个地方 引用它时,计数器值就加一;当引用失效时,计数器值就减一;任何时刻计数器为零的对象就是不可 能再被使用的。
引用计数算法(Reference Counting)虽然占用了一些额外的内存空间来进行计数,但 它的原理简单,判定效率也很高,在大多数情况下它都是一个不错的算法。
缺陷:
- public class ReferenceCountingGc {
- public object instance = null ;
- public static void testGc ( ) {
- ReferenceCountingGc objA = new ReferenceCountingGc ( );
- ReferenceCountingGc objB = new ReferenceCountingGC ( ) ;
- objA.instance = objB;
- objB.instance = objA;
- objA = null;
- objB =null;
- //假设在这行发生Gc,objA和objB是否能被回收?
- system. gc ( );
- }
- }
结果:objA和objB并没有被回收,因为虽然最后两个对象都赋值为空,但是二者之间任然存在相互引用,因此引用计数器不为零。这也从侧面说明了Java虚拟机并不是通过引用计数算法来判断对象 是否存活的。
当前主流的商用程序语言(Java、C#,上溯至前面提到的古老的Lisp)的内存管理子系统,都是 通过可达性分析(Reachability Analysis)算法来判定对象是否存活的。这个算法的基本思路就是通过 一系列称为“GC Roots”的根对象作为起始节点集,从这些节点开始,根据引用关系向下搜索,搜索过 程所走过的路径称为“引用链”(Reference Chain),如果某个对象到GC Roots间没有任何引用链相连, 或者用图论的话来说就是从GC Roots到这个对象不可达时,则证明此对象是不可能再被使用的。
其中,GC Roots包括以下几种:
虚拟机栈(栈帧中的局部变量表)中引用的对象;
方法区中类静态属性引用的对象;
方法区中常量引用的对象;
本地方法栈中Native方法引用的对象;
算法分为“标记”和“清除”两个阶段:首先标记出所有需要回 收的对象,在标记完成后,统一回收掉所有被标记的对象,也可以反过来,标记存活的对象,统一回 收所有未被标记的对象。标记过程就是对象是否属于垃圾的判定过程。
缺点:
具体内存区域看这:Java虚拟机中的年轻代、老年代、永久代图解版
解决标记-清除算法面对大量可回收对象时执行效率低 的问题
将可用 内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块的内存用完了,就将还存活着 的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。
具体内存区域看这:Java虚拟机中的年轻代、老年代、永久代图解版
标记-复制算法在对象存活率较高时就要进行较多的复制操作,效率将会降低
标记过程仍然与“标记-清除”算法一样,但后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象都向内存空间一端移动,然后直接清理掉边界以外的内存。
标记-清除算法与标记-整理算法的本质差异在于前者是一种非移动式的回收算法,而后者是移动式的。
如果移动存活对象,尤其是在老年代这种每次回收都有大量对象存活区域,移动存活对象并更新 所有引用这些对象的地方将会是一种极为负重的操作,而且这种对象移动操作必须全程暂停用户应用 程序才能进行,这就更加让使用者不得不小心翼翼地权衡其弊端了,像这样的停顿被最初的虚拟机 设计者形象地描述为“Stop The World”。————来自周志明《深入理解java虚拟机》
“Stop The World”:JVM由于要执行GC而停止了应用程序的执行,这种情形会在任何一种GC算法中发生。此时除了GC所执行的线程之外,所有线程都处于等待状态直到GC完成。
7种作用于不同分代的收集器,其中用于回收新生代的收集器包括Serial、PraNew、Parallel Scavenge,回收老年代的收集器包括Serial Old、Parallel Old、CMS,还有用于回收整个Java堆的G1收集器。(了解即可)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。