说到Java,一定绕不开GC,尽管不是Java首创的,但Java一定是使用GC的代表。GC就是垃圾回收,更直接点说就是内存回收。是对内存进行整理,从而使内存的使用尽可能大的被复用。 一直想好好写一篇关于GC的文章,可是却发现要写的东西太大了,不是一篇博客能简单的介绍完的。所以打算拆分成若干篇博客,一点点的总结下来。 本篇主要介绍的是GC中的常用算法。这些算法被广泛的应用于各个内存管理语言的虚拟机中,或者是各大常用的操作系统中。 说到GC,也就是垃圾回收,那么需要做的事有两件:

第一件是查找到哪些内存中的对象是已经废弃掉的。
第二件事是如何清理掉这些已经废弃掉的数据。
本文先来说说后者,如何清除掉这些内存中的废弃数据。

1、标记清除算法Mark-Sweep

这种算法是最简单最直接的算法,也是其它算法的一些最初思路。标记清除算法其实就是对内存中的对象依次的进行判断,如果对象需要回收那么就打一个标记,如果对象仍然需要使用,那么就保留下来。这样经过一次迭代之后,所有的对象都会被筛选判(防盗连接:本文首发自http://www.cnblogs.com/jilodream/ )断一次。紧接着会对内存中已经标记的对象依次进行清除。 这个算法比较简单粗暴,实现起来比较简单。但是会留下两个比较麻烦的问题: (1)标记和清除需要两遍循环内存中的对象,标记本身也是一个比较麻烦的工作,因此这种算法的效率不是特别的高。 (2)对于分配的内存来说,往往是连续的比较好,因为这样有利于分配大数据的对象。倘若当前内存中都是小段的内存碎片,会知道需要分配大段内存时,没有可以放置的位置,而触发内存回收。也就是空间不足而导致频繁GC和性能下降。

2、复制算法Copying

我在使用数据库的过程中,曾经遇到这样一个问题,表中的数据量相对来说比较大,大概30万行,需要使用多个苛刻的条件删除其中的大部分数据(因此无法使用索引),而只保留其中的较少数据。常规的delete语法使用起来是超时的。于是我查看维护人员的sql,发现一个很有意思的逻辑。首先查出数据库表中需要保留的数据,放到一张临时表中。然后彻底删除掉原有的数据表。然后把这张临时创建表的表名,改为当初的表名。这是一种典型的空间换取时间的方法。而复制算法就是这样一个思路。 复制算法中,会将内存划分为两块相等大小的内存区域A/B,然后生成的数据会存放在A区,当A区剩余空间不足以存放下一个新创建的对象时,系统就会将A区中的有效对象全部复制到B区中,而且是连续存放的。然后直接清空A区中的所有对象。 由于编程语言中的对象,大部分在创建后很快就(防盗连接:本文首发自http://www.cnblogs.com/jilodream/ )会被回收掉,所以我们需要复制的对象其实并不多。 Java中的实现是这样的: Java中将Eden和Survivor区同时作为复制算法的使用区域。Survivor又分为From区和To区。这块内容可以参考我的另外一篇博客有详细的介绍:。每次GC的时候都会将Eden和Survivor的From区中的有效对象进行标记,一同复制到Survivor的To区。然后彻底清除原来的Eden区和From区的内存对象。与此同时To区就是下一次回收的From区。

复制算法的缺点: 算法使用了空间换取时间的思路,因此需要一块空白的区域作为内存对象要粘贴的区域。这无疑会造成一种浪费。尤其是内存较小时。 算法每次清除无效对象时,都要进行一次复制粘贴的对象转移,因此对使用场景是有限制的。只有在有效对象占据总回收内存是非常小的时候,这种算法的性价比才会达到最高。否则大量的复制动作所浪费的时间可能要远远大于空间换取时间得到的收益。因此这种算法在Jvm中,也只被用来作为初级的对象回收。因为这时的有效对象比例最低,算法的性价比是最高的。

3、 标记整理算法 Mark-Compact

复制算法需要一块额外的内存空间,用于存放幸存的内存对象。这无疑造成了内存的浪费。我们还可以在原有的标记清除算法的基础上,提出了优化方案。也就是标记到的可用对象整体向一侧移动,然后直接清除掉可用对象边界意外的内存。(防盗连接:本文首发自http://www.cnblogs.com/jilodream/ )这样既解决了内存碎片的问题。又不需要原有的空间换时间的硬件浪费。由于老年代中的幸存对象较多,而且对象内存占用较大。这就使得一旦出现内存回收,需要被回收的对象并不多,碎片也就相对的比较少。所以不需要太多的复制和移动步骤。因此这种方法常常被应用到老年代中。 标记整理算法的缺点: 标记整理算法由于需要不断的移动对象到另外一侧,而这种不断的移动其实是非常不适合杂而多的小内存对象的。因此在使用场景上,就注定限制了标记整理算法的使用不太适合频繁创建和回收对象的内存中。

4、分代收集算法  Generational Collection

这种算法就是将内存以代的形式划分,然后针对情况分别使用性价比最高的算法进行处理。在Java中,一般将堆分为老年代和新生代。新创建的对象往往被放置在新生代中。而经过不断的回收,逐渐存活下来的对象被安置到了老年代中。越新的对象越可能被回收,越老的对象反而会存活的越久。因此针对这两种场景,新生代和老年代也会分别采用前文所述的两种算法进行清理。

ps:话说现在写篇博客越来越难了,今天以为画个图就可以发布了,结果画图画了一个小时。哎

JVM GC-----垃圾回收算法的更多相关文章

  1. JVM(九):垃圾回收算法

    JVM(九):垃圾回收算法 在本文中,我们将从概念模型的角度探讨 JVM 是如何回收对象,包括 JVM 是如何判断一个对象已经死亡,什么时候在哪里进行了垃圾回收,垃圾回收有几种核心算法,每个算法优劣是 ...

  2. JVM G1垃圾回收算法简要介绍

    JVM G1垃圾回收算法简要介绍 G1的特点 能够像CMS垃圾回收算法一样并发操作应用线程(潜台词:多核) 无需太长时间即可压缩空闲内存空间(潜台词:不会引起太多的GC停顿时间) 尽可能地让GC时长可 ...

  3. jvm详情——3、JVM基本垃圾回收算法回收策略

    JVM基本垃圾回收算法回收策略 引用计数(Reference Counting):比较古老的回收算法.原理是此对象有一个引用,即增加一个计数,删除一个引用则减少一个计数.垃圾回收时,只用收集计数为0的 ...

  4. JVM常见垃圾回收算法

    jdk1.7.0_79 众所周知,Java是一门不用程序员手动管理内存的语言,全靠JVM自动管理内存,既然是自动管理,那必然有一个垃圾内存的回收机制或者回收算法.本文将介绍几种常见的垃圾回收(下文简称 ...

  5. jvm的垃圾回收算法

    一.对象存活判断判断对象是否存活一般有两种方式:1.引用计数:每个对象有一个引用计数属性,新增一个引用时计数加1,引用释放时计数减1,计数为0时可以回收.此方法简单,无法解决对象相互循环引用的问题.2 ...

  6. Java GC 垃圾回收算法 内存分配

    垃圾回收(Garbage Collection, GC)是Java不同于c与c++的重要特性之一. 他帮助Java自动清空堆中不再使用的对象. 由于不需要手动释放内存,程序员在编程中也可以减少犯错的机 ...

  7. 深入理解JVM一垃圾回收算法

    我们都知道java语言与C语言最大的区别就是内存自动回收,那么JVM是怎么控制内存回收的,这篇文章将介绍JVM垃圾回收的几种算法,从而了解内存回收的基本原理. 一.stop the world 在介绍 ...

  8. jvm学习-垃圾回收算法(三)

     垃圾回收算法  引用计数法 比较古老的一种垃圾回收算法.在java的GC并没有采用 增加一个引用 引用+1 减少一个引用引用减一 每次清除引用为0的的对象 缺点:不能回收循环引用的垃圾对象 标记清除 ...

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

    线程与进程(了解)→JVM→字节码→GC 一.程序 = 算法 + 数据结构(大佬) 二.程序 = 框架 + 业务逻辑(现实) 1.线程与进程.同步与异步 1.1进程是什么? 进程就是操作系统控制的基本 ...

  10. 深入探究JVM之垃圾回收算法实现细节

    @ 目录 前言 垃圾回收算法实现细节 根节点枚举 安全点 安全区域 记忆集和卡表 写屏障 并发的可达性分析 低延迟GC Shenandoah ZGC 总结 前言 本篇紧接上文,主要讲解垃圾回收算法的实 ...

随机推荐

  1. Callable与Future

    本文可作为传智播客<张孝祥-Java多线程与并发库高级应用>的学习笔记. 在前面写的代码中,所有的任务执行也就执行了,run方法的返回值为空. 这一节我们说的Callable就是一个可以带 ...

  2. LeetCode之“树”:Symmetric Tree && Same Tree

    Symmetric Tree 题目链接 题目要求: Given a binary tree, check whether it is a mirror of itself (ie, symmetric ...

  3. Aprior算法

    在关联规则挖掘领域最经典的算法法是Apriori,其致命的缺点是需要多次扫描事务数据库.于是人们提出了各种裁剪(prune)数据集的方法以减少I/O开支,韩嘉炜老师的FP-Tree算法就是其中非常高效 ...

  4. DB 查询分析器 6.03 如何灵活、快捷地操作国产达梦数据库

    DB 查询分析器 6.03 如何灵活.快捷地操作国产达梦数据库 马根峰 (广东联合电子服务股份有限公司, 广州 510300) 摘要       本文详细地介绍了"万能数据库查询分析器&qu ...

  5. Sample Code for Qp_preq_pub.Price_request Api to Simulate an Ask for Promotion Modifier

    DECLARE p_line_tbl QP_PREQ_GRP.LINE_TBL_TYPE; p_qual_tbl QP_PREQ_GRP.QUAL_TBL_TYPE; p_line_attr_tbl ...

  6. Spring--ClassPathResource

    /* * 用一个给定的类加载器或者给定的类来加载资源 */ public class ClassPathResource extends AbstractFileResolvingResource { ...

  7. 如果去掉UITableView上的section的headerView和footerView的悬浮效果

    项目需要cell的间距,又不需要悬浮效果,百度之后找到这个方法,记录一下,备忘. 用UIScrollView的代理方法实现 - (void)scrollViewDidScroll:(UIScrollV ...

  8. obj-c编程09:块的语法

    在obj-c中,有一种和C截然不同的东西--块.块可以在外边定义,也可以在函数或方法内部定义,可以被赋值给一个变量,然后用该变量调用.默认情况下块对外部变量的访问只能读不能写,除非用__block显示 ...

  9. err:安装程序试图挂载映像 1(缺少ISO 9660图像)

    一般出现此错误是因为你没有把相应的CentOS-6.4-i386-bin-DVD1.iso文件放入到你装系统所引导的盘中,造成找不到挂载映像文件. ubuntu-12.04.3-desktop-i38 ...

  10. ubuntu下无法编译ruby-2.1.5提示something wrong with CFLAGS -arch x86_64

    在Mac OS X10.10下以下语句运行没有问题: ./configure -prefix=/Users/apple/src/ruby_src/ruby2.1.5_installed --with- ...