一、认识垃圾回收

谈到垃圾回收(Garbage Collection,简称GC),GC中的垃圾,特指存在于内存中的、不会再被使用的对象。对于内存空间的管理来说,识别和清理垃圾对象是至关重要的。

二、常用的垃圾回收算法

2.1 引用计数法(Reference Counting)

引用计数法是最经典也最古老的一种垃圾收集算法。

引用计数器的实现很简单,对于一个对象A,只有有任何一个对象引用了A,则A的引用计数器就加1,当引用失效时,引用计数器减1。只有对象A的引用计数器的值为0,则对象A就不可能再被使用。

引用技术器的实习也非常简单,只需为每个对象配备一个整型的计数器即可。但是,引用计数器有两个非常严重的问题:

  • 无法处理循环引用的情况。因此,在Java的垃圾回收器中,没有使用这种算法。
  • 引用计数器要求在每次因引用产生和消除的时候,需要伴随一个加法操作和减法操作,对系统性能会有一定的影响。

2.2 标记清除法(Mark-Sweep)

标记清除算法是现代垃圾回收算法的思想基础。标记清除算法将垃圾回收分为两个阶段:标记阶段和清除阶段。一种可行的实现是,在标记阶段,首先通过根节点,标记所有从根节点开始的可达对象。因此,未被标记的对象就是未被引用的垃圾对象。然后,在清除阶段,清除所有未被标记的对象。标记清除算法可能产生的最大问题就是空间碎片。

  • 可达对象:通过根对象进行引用搜索,最终可以达到的对象。
  • 不可达对象: 通过根对象进行引用搜索,最终没有被引用到的对象。

在Java语言中,作为GC Roots的对象包括以下几种:

  • 虚拟机栈(栈帧中的本地变量表)中引用的对象。
  • 方法去中类静态变量属性引用的对象。
  • 方法区中常量引用的对象。
  • 本地方法栈中JNI(即一般说的Native方法)引用的对象。

它主要不足有两个:一是效率问题,标记和清除两个过程的效率都不高;另一个是空间问题,标记清除之后会产生大量不连续的内存碎片,空间碎片太多会导致以后在程序运行过程中需要分配较大对象时,无法找到足够的连续内存而不得不提前出发另一次垃圾收集动作。

2.3 复制算法(Copying)

复制算法的核心是:将原有的内存空间分为两块,每次只使用其中一块,在垃圾回收时,将正在使用的内存中的存活对象复制到未使用的内存块中,之后,清除正在使用的内存块中的所有对象,交换两个内存的角色,完成垃圾回收。

在Java的新生代串行垃圾回收器中,使用了复制算法的思想。

在垃圾回收时,eden空间中存活的对象会被复制到未使用的survivor空间中(假设是to),正在使用的survivor空间(假设是from)中的年轻对象也会被复制到to空间中(大对象,或者老年对象会直接进入老年代,如果to空间已满,则对象也会直接进入老年代)。此时,eden空间和from空间中的剩余对象就是垃圾对象,可以直接清空,to空间则存放此次回收后的存活对象。这种改进的复制算法,既保证了空间的连续性,又避免了大量的内存空间浪费。当所有存活对象都被复制到survivor区后(图中为to)。简单的清空eden区和备用的survivor区(图中为from)即可。

复制算法比较适用于新生代。因为在新生代,垃圾对象通常会多于存活对象。复制算法的效果会比较好。

2.4 标记压缩法(Mark-Compact)

标记压缩算法是一种老年代的回收算法。它在标记清除算法的基础上做了一些优化。和标记清除算法一样,标记压缩算法也首先需要从根节点开始,对所有可达对象做一次标记。但之后,他并不是简单的清理未标记的对象,而是将所有的存活对象压缩到内存的一端。之后清理边界外所有的空间。这种方法既避免了碎片的产生,又不需要两块相同的内存空间,因此,其性价比较高。

2.5 分代算法(Generational Collecting)

根据垃圾回收对象的特性,使用合适的算法回收,分代算法就是基于这种思想。新生代使用复制算法,老年代使用标记压缩算法或标记清除算法,以提高垃圾回收效率。

2.6 分区算法(Region)

分代算法将按照对象的生命周期长短划分成两个部分,分区算法将整个堆空间划分成梁旭的不同小区间。每个小区间都独立使用,独立回收。这种算法的好处是可以控制一次回收多少个小区间。

一般来说,在相同的条件下,堆空间越大,一次GC时所需要的时间就越长,从而产生的停顿也越长。为了更好地控制GC产生的停顿时间,将一块大的内存区域分割为多个小块,根据目标的停顿时间,每次合理的回收若干个小区间,而不是整个堆空间,从而减少一次GC所产生的停顿。

三、判断可触及性

垃圾回收的基本思想是考察每一个对象的可触及性,即从根节点开始是否可以访问到这个对象,如果可以,则说明当前对象正在被使用,如果从所有的根节点都无法访问到某个对象,说明对象已经不再使用了,一般来说,此对象需要被回收。但事实上,一个无法触及的对象有可能在某一条件下“复活”自己,如果这样,那么对他的回收就是不合理的,为此,需要给出一个对象可触及性状态的定义,并规定在什么状态下,才可以安全的回收对象。

深入JVM-垃圾回收概念与算法的更多相关文章

  1. jvm 垃圾回收概念和算法

    1.概念 GC 中的垃圾,特指存在于内存中.不会再被使用的对象.垃圾回收有很多种算法,如引用计数法.复制算法.分代.分区的思想. 2.算法 1.引用计数法:对象被其他所引用时计数器加 1,而当引用失效 ...

  2. jvm 垃圾回收机制和算法(转)

    stop-the-world 在学习Java GC 之前,我们需要记住一个单词:stop-the-world .它会在任何一种GC算法中发生.stop-the-world 意味着JVM因为需要执行GC ...

  3. JVM垃圾回收机制和常用算法

    由于疫情的原因,所以目前一直在家远程办公,所以很多时间在刷面试题,发现2019大厂的面试虽然种类很多,但是总结了一下发现主要是这几点:算法和数据结构. JVM.集合.多线程.数据库这几点在面试的时候比 ...

  4. JVM虚拟机(四):JVM 垃圾回收机制概念及其算法

    垃圾回收概念和其算法 谈到垃圾回收(Garbage Collection)GC,需要先澄清什么是垃圾,类比日常生活中的垃圾,我们会把他们丢入垃圾箱,然后倒掉.GC中的垃圾,特指存于内存中.不会再被使用 ...

  5. JVM垃圾回收算法及回收器详解

    引言 本文主要讲述JVM中几种常见的垃圾回收算法和相关的垃圾回收器,以及常见的和GC相关的性能调优参数. GC Roots 我们先来了解一下在Java中是如何判断一个对象的生死的,有些语言比如Pyth ...

  6. 谈谈JVM垃圾回收机制及垃圾回收算法

    一.垃圾回收机制的意义 Java语言中一个显著的特点就是引入了垃圾回收机制,使c++程序员最头疼的内存管理的问题迎刃而解,它使得Java程序员在编写程序的时候不再需要考虑内存管理.由于有个垃圾回收机制 ...

  7. Java基础:JVM垃圾回收算法

    众所周知,Java的垃圾回收是不需要程序员去手动操控的,而是由JVM去完成.本文介绍JVM进行垃圾回收的各种算法. 1. 如何确定某个对象是垃圾 1.1. 引用计数法 1.2. 可达性分析 2. 典型 ...

  8. JVM(四)垃圾回收的实现算法和执行细节

    全文共 1890 个字,读完大约需要 6 分钟. 上一篇我们讲了垃圾标记的一些实现细节和经典算法,而本文将系统的讲解一下垃圾回收的经典算法,和Hotspot虚拟机执行垃圾回收的一些实现细节,比如安全点 ...

  9. 简述 JVM 垃圾回收算法

    经典垃圾回收 标记-清除(Mark-Sweep) 研发园开了家新餐厅,餐厅老板在考虑如何回收餐盘时首先使用了最简单的方式,那就是服务员在顾客用餐的过程中,不定时的观察餐厅,针对用完餐的顾客记录他们的位 ...

  10. JVM垃圾回收算法解析

    JVM垃圾回收算法解析 标记-清除算法 该算法为最基础的算法.它分为标记和清除两个阶段,首先标记出需要回收的对象,在标记结束后,统一回收.该算法存在两个问题:一是效率问题,标记和清除过程效率都不太高, ...

随机推荐

  1. 基于FPGA的电压表与串口通信(下)

    实验操作 上电 接入5V电源,用配套的线,USB那端接电脑即可: 电源开关 按下电源开关 接串口线 接下载线 现在电脑装串口线驱动 R340qd.zip 双击进行安装 设置串口调试助手 Com1要根据 ...

  2. Xen

    Xen是一个开放源代码虚拟机监视器,由剑桥大学开发.它打算在单个计算机上运行多达128个有完全功能的操作系统. 在旧(无虚拟硬件)的处理器上执行Xen,操作系统必须进行显式地修改(“移植”)以在Xen ...

  3. Unix 复制文件至指定目录

    cp /gaps/log/20160504/bxdx_20160504.log.Z   /home 将/gaps/log/20160504/bxdx_20160504.log.Z 文件复制到home路 ...

  4. python作为一种胶水和c/c++

    如果需要用 Python 调用 C/C++ 编写的第三方库,只需要一个脚本语言来粘合它们.这个时候,用 Python ctypes 可以很方便地实现调用. StackOverflow 上的 Calli ...

  5. 北大OJ 1001题

    题目:输入一序列的正实数和幂次(正整数)对,然后打印结果(具体的比这个精细) 这道题是关于大数计算的(大数求幂),从开始建立思路,到写代码.调式到最后被AC以及最终的优化,总共用了差不多一天的时间.开 ...

  6. java虚拟机和Dalvik虚拟机的区别

    java虚拟机和Dalvik虚拟机的区别: java虚拟机Dalvik虚拟机 java虚拟机基于栈. 基于栈的机器必须使用指令来载入和操作栈上数据,所需指令更多更多dalvik虚拟机是基于寄存器的 j ...

  7. springMvc请求的跳转和传值

    forword跳转页面的三种方式: 1.使用serlvet /** * 使用forward跳转,传递基本类型参数到页面 * 注意: * 1.使用servlet原生API Request作用域 * */ ...

  8. Kernel Methods (3) Kernel Linear Regression

    Linear Regression 线性回归应该算得上是最简单的一种机器学习算法了吧. 它的问题定义为: 给定训练数据集\(D\), 由\(m\)个二元组\(x_i, y_i\)组成, 其中: \(x ...

  9. js-处理回车事件

    /**回车 */ function enterkey() { //兼容IE或其它其它浏览器 var event = arguments[0] || window.event; //兼容IE或其它浏览器 ...

  10. selenium+eclispse里代码备注

    1.火狐.谷歌和IE浏览器引擎都要重新下载selenium官网引擎,并设置路径才可以支持selenium3 而狐火用自己的引擎不用设置路径既可以支持selenium2也支持selenium3,谷歌和I ...