JVM-内存回收算法--复制算法

复制算法,它将堆上的内存分为两个大小相等的区域,一个是空闲区域,一个是活动区域。在程序运行中,实际使用的是活动区域,也就是有50%的空间被浪费掉。

复制算法的实现过程:1.找出活动空间中所有存活的对象。2.将这些存活的对象复制到空闲区域。3.将之前的活动空间清空,然后,就变为空闲空间了,而存活对象所在的区域,则变为活动空间了。

复制算法的优点,就是,内存回收完毕后,有一大片连续的可用空间。缺点,当然是,在程序运行期间,有50%的内存空间被放着,只有在发生内存回收的时候,GC才会借用空闲区域来实现内存回收工作。

------------------------------------------------------------转载------------------------------------------------------------------------------------------

下文是转载自一个博客上的文章,它形象的介绍了复制算法。

http://www.cnblogs.com/zuoxiaolong/p/jvm5.html

复制算法

我们首先一起来看一下复制算法的做法,复制算法将内存划分为两个区间,在任意时间点,所有动态分配的对象都只能分配在其中一个区间(称为活动区间),而另外一个区间(称为空闲区间)则是空闲的

当有效内存空间耗尽时,JVM将暂停程序运行,开启复制算法GC线程。接下来GC线程会将活动区间内的存活对象,全部复制到空闲区间,且严格按照内存地址依次排列,与此同时,GC线程将更新存活对象的内存引用地址指向新的内存地址

此时,空闲区间已经与活动区间交换,而垃圾对象现在已经全部留在了原来的活动区间,也就是现在的空闲区间。事实上,在活动区间转换为空间区间的同时,垃圾对象已经被一次性全部回收。

听起来复杂吗?

其实一点也不复杂,有了上一章的基础,相信各位理解这个算法不会费太多力气。LZ给各位绘制一幅图来说明问题,如下所示。

其实这个图依然是上一章的例子,只不过此时内存被复制算法分成了两部分,下面我们看下当复制算法的GC线程处理之后,两个区域会变成什么样子,如下所示。

可以看到,1和4号对象被清除了,而2、3、5、6号对象则是规则的排列在刚才的空闲区间,也就是现在的活动区间之内。此时左半部分已经变成了空闲区间,不难想象,在下一次GC之后,左边将会再次变成活动区间。

很明显,复制算法弥补了标记/清除算法中,内存布局混乱的缺点。不过与此同时,它的缺点也是相当明显的。

1、它浪费了一半的内存,这太要命了。

2、如果对象的存活率很高,我们可以极端一点,假设是100%存活,那么我们需要将所有对象都复制一遍,并将所有引用地址重置一遍。复制这一工作所花费的时间,在对象存活率达到一定程度时,将会变的不可忽视

所以从以上描述不难看出,复制算法要想使用,最起码对象的存活率要非常低才行,而且最重要的是,我们必须要克服50%内存的浪费

版权声明



作者:zuoxiaolong(左潇龙)

出处:博客园左潇龙的技术博客--http://www.cnblogs.com/zuoxiaolong

您的支持是对博主最大的鼓励,感谢您的认真阅读。

本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

------------------------------------------------------------转载------------------------------------------------------------------------------------------

JVM-内存回收算法--复制算法

时间: 2024-09-29 02:55:37

JVM-内存回收算法--复制算法的相关文章

JVM内存模型与GC算法(简介)

JVM内存模型如上图,需要声明一点,这是<Java虚拟机规范(Java SE 7版)>规定的内容,实际区域由各JVM自己实现,所以可能略有不同.以下对各区域进行简短说明. 1.1程序计数器 程序计数器是众多编程语言都共有的一部分,作用是标示下一条需要执行的指令的位置,分支.循环.跳转.异常处理.线程恢复等基础功能都是依赖程序计数器完成的. 对于Java的多线程程序而言,不同的线程都是通过轮流获得cpu的时间片运行的,这符合计算机组成原理的基本概念,因此不同的线程之间需要不停的获得运行,挂起等待

Java基础-JVM内存回收

Sun的JVMGenerationalCollecting(垃圾回收)原理是这样的:把对象分为年青代(Young).年老代(Tenured).持久代(Perm),对不同生命周期的对象使用不同的算法.(基于对对象生命周期分析) 1.Young(年轻代) 年轻代分三个区.一个Eden区,两个Survivor区.大部分对象在Eden区中生成.当Eden区满时,还存活的对象将被复制到Survivor区(两个中的一个),当这个Survivor区满时,此区的存活对象将被复制到另外一个Survivor区,当这

JVM垃圾回收2(垃圾收集算法)

根据<深入理解java虚拟机>这本书总结 一.关于几个概念:(标记垃圾算法.垃圾收集算法.垃圾收集器) 前面说了如何寻找jvm垃圾,有两种方法:引用计数法/可达性算法.这篇准备讲,标记完垃圾之后,回收的算法,这里的算法只是垃圾回收的思想.后面会讲到多种垃圾收集器,这里的垃圾收集器就是运用了垃圾手机算法的思想,可以说是具体实现. 这里还是想多余的说一下这三个概念: 垃圾标记算法:标记垃圾的方法 垃圾收集算法:一种回收思想,供垃圾收集器使用.可能用在年轻代,也可能用在老年代(当然现在来说老年代和年

JVM垃圾回收机制与算法

JVM内存由几个部分组成:堆.方法区.栈.程序计数器.本地方法栈 JVM垃圾回收仅针对公共内存区域,即:堆和方法区进行,因为只有这两个区域在运行时才能知道需要创建些对象,其内存分配和回收都是动态的. 一.垃圾回收策略 1.1分代管理 将堆和方法区按照对象不同年龄进行分代: (Young Generation and Old Generation)堆中会频繁创建对象,基于一种分代的思想,按照对象存活时间将堆划分为新生代和旧生代两部分,并不是一次垃圾回收新生代存活的对象就放入旧生代, 而是要经过几次

JVM垃圾回收概念和算法

GC中的垃圾:特指存在于内存中.不会再使用的对象. 内存泄漏和内存溢出的区别: 内存泄漏:内存空间忘记回收,垃圾对象永远无法被回收 内存溢出:垃圾对象(不满足回收条件)所耗内存持续上升,导致内存溢出. 1 常用的垃圾回收算法 引用计数法.标记压缩法.标记清除法.复制算法和分代.分区 1)引用计数法:

jvm内存回收机制

Java垃圾回收概况 Java GC(Garbage Collection,垃圾收集,垃圾回收)机制,是Java与C++/C的主要区别之一,作为Java开发者,一般不需要专门编写内存回收和垃圾清理代 码,对内存泄露和溢出的问题,也不需要像C程序员那样战战兢兢.这是因为在Java虚拟机中,存在自动内存管理和垃圾清扫机制.概括地说,该机制对 JVM(Java Virtual Machine)中的内存进行标记,并确定哪些内存需要回收,根据一定的回收策略,自动的回收内存,永不停息(Nerver Stop

GC算法-复制算法

概述 复制算法就是将内存空间二等分, 每次只使用其中一块. 当执行GC时, 讲A部分的所有活动对象集体移到B中, 就可以讲A全部释放. 画个图就是: ? 在执行GC前, 内存长这样: ? 当执行GC后, 内存就变成这样了: 还记得标记清除算法的问题是什么吗? 内存碎片化严重. 现在好了, 碎片化问题解决了, 每次GC执行后, 内存空间都是连续的啦. 实现 想一想GC执行的步骤是什么? 很简单啊, 遍历所有可访问的对象, 将所有对象的复制到另一块内存中. 完毕. 遍历所有根集合的对象, 跳过. 将

第三章 JVM内存回收区域+对象存活的判断+引用类型+垃圾回收线程

注意:本文主要参考自<深入理解Java虚拟机(第二版)> 说明:查看本文之前,推荐先知道JVM内存结构,见<第一章 JVM内存结构> 1.内存回收的区域 堆:这是GC的主要区域 方法区:回收两样东西 无用的类 废弃的常量 栈和PC寄存器是线程私有区域,不发生GC 2.怎样判断对象是否存活 垃圾回收:回收掉死亡对象所占的内存.判断对象是否死亡,有两种方式: 引用计数法 原理:给对象添加一个引用计数器,每当有一个地方引用它时,计数器值+1:引用失效时,计数器值-1 实际中不用,不用的两

关于jvm内存回收问题

目前内存的动态分配与内存回收技术已经相当成熟,那为什么我们还要去了解GC和内存分配呢?答案很简单:当需要排查各种内存溢出,内存泄漏问题时,当垃圾收集成为系统达到更高并发量的瓶颈时,我们就需要对这些“自动化”的技术实施必要的监控和调节. 有三部分内存区域:程序计数器,虚拟机栈,本地方法栈,它们随线程而生,随线程而灭.栈中的栈帧随着方法的进入和退出而有条不紊的进行着岀栈和如栈操作.每一个栈帧中分配多少内存基本上是在类结构确定下来时就已知的,因此这几个区域的内存分配和回收都具备确定性,在这几个区域内就