基于JVM 中常见垃圾收集算法介绍

JVM 中常见的垃圾收集算法有四种:

标记-清除算法(Mark-Sweep);

复制算法(Copying);

标记-整理(Mark-Compact);

分代收集;

下面我们来一一介绍:

一、标记-清除算法(Mark-Sweep)

这是最基础的垃圾收集算法,算法分为“标记”和“清除”两个阶段:首先标记出所有需要回收的对象,在标记完成后统一回收掉所有被标记的对象。它的主要缺点有两个:一个是效率问题,标记和清除效率都不高;另一个是空间问题,标记清除后会产生大量不连续的内存碎片,空间碎片太多可能会导致分配大对象时没有足够的大的连续空间,而不得不提前触发另一次垃圾收集动作。

标记-清除算法示意图

二、复制算法(Copying)

为了解决效率问题,有了“复制”的算法,他将可用内存分为大小相同两块。每次只用一块,当一块空间用完了,就将还存活的对象复制到另一块上,然后将刚使用过的内存空间一次清理掉。这样使得每次都是对其中的一块进行内存回收,内存分配时也就不用考虑内存碎片等复杂情况。实现简单,运行高效。只是这种算法的代价是将内存缩小到原来的一半,代价太贵了点。实际上,新生代中的对象98%都是朝生夕死,所以不需要按1:1的比例来分内存,而是将内存分为一块较大的Eden空间和两块较小的Survivor空间,每次使用Eden空间和其中一块Survivior空间。当回收时,将Eden和Survivor中还存活的对象一次性的拷贝到另一块Suivivior中,最后清理掉Eden和刚用过的Survivor空间。

复制算法示意图

三、标记-整理(Mark-Compact)

复制收集算法在对象存活率高的时候就要执行较多的复制操作,效率将会变低。更关键的是,如果不想浪费50%的空间,就需要有额外的空间进行分配担保用于应付半区内存中所有对象都100%存活的极端情况,所以在老年代一般不能直接选用这种算法。

因此人们提出另外一种“标记-整理”(Mark-Compact)算法由于老年代中的对象生存周期都较长,有人提出“标记-整理”算法,标记过程和“标记-清理”一样,但在清除已死对象的同时会对存活对象进行整理,这样可以减少碎片空间。

标记-整理算法示意图

四、分代收集

当前商业虚拟机的垃圾收集都是采用“分代收集”(Generational Collecting)算法,这种算法并没有什么新的思想出现,只是根据对象不同的存活周期将内存划分为几块。一般是把Java堆分作新生代和老年代,这样就可以根据各个年代的特点采用最适当的收集算法。在新生代中,每次垃圾收集时都发现有大批对象死去,只有少量存活,那就用复制算法,只要少量复制成本就可以完成收集。而老年代中因为对象的存活率较高、周期长,就用“标记-整理”或“标记-清除”算法来回收。

以上这篇基于JVM 中常见垃圾收集算法介绍就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们。

您可能感兴趣的文章:

  • JVM垃圾收集器详解
  • Java虚拟机JVM性能优化(三):垃圾收集详解
(0)

相关推荐

  • Java虚拟机JVM性能优化(三):垃圾收集详解

    Java平台的垃圾收集机制显著提高了开发者的效率,但是一个实现糟糕的垃圾收集器可能过多地消耗应用程序的资源.在Java虚拟机性能优化系列的第三部分,Eva Andreasson向Java初学者介绍了Java平台的内存模型和垃圾收集机制.她解释了为什么碎片化(而不是垃圾收集)是Java应用程序性能的主要问题所在,以及为什么分代垃圾收集和压缩是目前处理Java应用程序碎片化的主要办法(但不是最有新意的). 垃圾收集(GC)的目的是释放那些不再被任何活动对象引用的Java对象所占用的内存,它是Java

  • JVM垃圾收集器详解

    说起垃圾收集(Garbage Collection,GC),大部分人都把这项技术当做Java语言的伴生产物.事实上,GC的历史远比Java久远,1960年诞生于MIT的Lisp是第一门真正使用内存动态分配和垃圾收集技术的语言.当List还在胚胎时期时,人们就在思考GC需要完成的3件事情: 哪些内存需要回收? 什么时候回收? 如何回收? 一.哪些内存需要回收? 从JVM区域结构看,可将这些区域划分为"静态内存"和"动态内存"两类.程序计数器.虚拟机栈.本地方法3个区域

  • 基于JVM 中常见垃圾收集算法介绍

    JVM 中常见的垃圾收集算法有四种: 标记-清除算法(Mark-Sweep): 复制算法(Copying): 标记-整理(Mark-Compact): 分代收集: 下面我们来一一介绍: 一.标记-清除算法(Mark-Sweep) 这是最基础的垃圾收集算法,算法分为"标记"和"清除"两个阶段:首先标记出所有需要回收的对象,在标记完成后统一回收掉所有被标记的对象.它的主要缺点有两个:一个是效率问题,标记和清除效率都不高:另一个是空间问题,标记清除后会产生大量不连续的内存

  • 基于jvm java内存区域的介绍

    jvm虚拟机在运行时需要用到的内存区域.广泛一点就是堆和栈,其实不然,堆和栈只是相对比较笼统的说法,真正区分有如下几个 先上图一: 总的就是 java的内存模型 内存模型又分堆内存(heap)和方法区(有时也称为non-heap)和栈 堆又分新生代(Young)和老年代(old/Tenured) 新生代又分默认比例为8:1:1的eden空间.from survivor空间.to survivor空间 当进行垃圾回收时,eden.survivor from 存活得对象会复制到servivor to

  • C++ STL中常见的算法使用方式

    目录 什么是STL? 0. < algorithm> 是什么: 1. Non-modifying sequence operations: 1.1 find:(Find value in range) 1.2 count:(Count appearances of value in range) 1.3 equal:(Test whether the elements in two ranges are equal) 1.4 search:(Search range for subsequen

  • 基于Python中的yield表达式介绍

    python生成器 python中生成器是迭代器的一种,使用yield返回函数值.每次调用yield会暂停,而可以使用next()函数和send()函数可以恢复生成器. 这里可以参考Python函数式编程指南:对生成器全面讲解 注意到yield是个表达式而不仅仅是个语句,所以可以使用x = yield r 这样的语法. 这个知识点在协程中需要使用.协程的概念指的是在一个线程内,一个程序中断去执行另一个程序,有点类似于CPU中断.这样减少了切换线程带来的负担,同时不需要多线程中的锁机制,因为不存在

  • java基础学习JVM中GC的算法

    在java学习到JVM时候,总会很多朋友问到关于GC算法的问题,小编在此给大家整理关于JVM中GC算法的原理以及图文详细分析,希望能够帮助你对这个GC算法的理解. JVM内存组成结构: (1)堆 所有通过new创建的对象都是在堆中分配内存,其大小可以通过-Xmx和-Xms来控制,堆被划分为新生代和旧生代,新生代又被进一步划分为Eden和Survivor区.Survivor被划分为from space 和 to space组成,结构图如下: (2)栈 每个线程 执行每个方法的时候都会在栈中申请一个

  • 基于C++中常见内存错误的总结

    在系统开发过程中出现的bug相对而言是比较好解决的,花费在这个上面的调试代价不是很大,但是在系统集成后的bug往往是难以定位的bug(最好方式是打桩,通过打桩可以初步锁定出错的位置,如:进入函数前打印日志,离开时再次打印日志).而这些难以定位的bug基本分为2类:内存错误和并非问题. 1.内存泄露如果在堆栈上分配的内存使用完成后没有释放就会造成内存泄露.少量的内存泄露不至于让程序崩溃,但是大量的内存泄露就会导致内存耗尽,后续内存分配失败,从而导致程序崩溃.长时间运行软件,即使只有一两处泄露,同样

  • 前端JS面试中常见的算法问题总结

    前言 学习数据结构与算法对于工程师去理解和分析问题都是有帮助的.如果将来当我们面对较为复杂的问题,这些基础知识的积累可以帮助我们更好的优化解决思路.下面罗列在前端面试中经常撞见的几个问题吧. Q1 判断一个单词是否是回文? 回文是指把相同的词汇或句子,在下文中调换位置或颠倒过来,产生首尾回环的情趣,叫做回文,也叫回环.比如 mamam redivider . 很多人拿到这样的题目非常容易想到用for 将字符串颠倒字母顺序然后匹配就行了.其实重要的考察的就是对于reverse的实现.其实我们可以利

  • 基于C++中常见编译错误的总结详解

    在日常编码过程中会遇见各种编译错误,本文对常见的编译错误进行分析总结.(基本的编译错误在这里不列举,后续后持续更新) 1.error c101008a解决方法该错误出现在项目升级过程中会出现,比如说项目从vs2008升级到vs2010.解决办法:在项目上点右键,清理(Clean),重新编译,问题解决 2.error C2252解决方法该错误主要在项目从vs2008升级到vs2010出先.error C2252: an explicit instantiation of a template ca

  • 基于java中BlockingQueue的使用介绍

    最近在维护一个java工程,在群里面也就聊起来java的优劣!无奈一些Java的终极粉丝,总是号称性能已经不必C++差,并且很多标准类库都是大师级的人写的,如何如何稳定等等.索性就认真研究一番,他们给我的一项说明就是,在线程之间投递消息,用java已经封装好的BlockingQueue,就足够用了. 既然足够用那就写代码测试喽,简简单单写一个小程序做了一番测试: 复制代码 代码如下: //默认包 import java.util.concurrent.*; import base.MyRunna

  • 快速理解Java垃圾回收和jvm中的stw

    Java中Stop-The-World机制简称STW,是在执行垃圾收集算法时,Java应用程序的其他所有线程都被挂起(除了垃圾收集帮助器之外).Java中一种全局暂停现象,全局停顿,所有Java代码停止,native代码可以执行,但不能与JVM交互:这些现象多半是由于gc引起. GC时的Stop the World(STW)是大家最大的敌人.但可能很多人还不清楚,除了GC,JVM下还会发生停顿现象. JVM里有一条特殊的线程--VM Threads,专门用来执行一些特殊的VM Operation

随机推荐