1. 哪些内存需要GC
    • 判断对象是否还存活

      • 引用计数法

        • 给对象中添加一个引用计数器,每当一个地方引用它时,计数器值就加1;当引用失效时,计数器的值就减1,任何时候计数器为0的对象就是不可能再被使用的。
        • 微软公司的COM技术,使用ActionScript3的FlashPlayer等都使用了引用计数算法来进行内存管理。
        • 但是Java虚拟机里面没有选用引用计数算法来管理内存,其中最主要的原因时它很难解决对象之间相互循环引用的问题
      • 可达性分析算法:
        • 在主流的商用程序语言(Java, C#, Lisp等)都是通过可达性分析算法来判断对象是否存活的。
        • 通过一些“GC Roots” 的对象作为起始点,从这些结点开始向下搜索,搜索所走过的路径称为引用链。当一个对象到GC Roots没有任何引用链相连时,则证明此对象时不可用的。
        • Java中可作为GC Roots 的对象包括:
          • 虚拟机栈(栈中的本地变量表) 中引用的对象
          • 方法区中类静态属性引用的对象
          • 方法区中常量引用的对象
          • 本地方法栈中JNI(一般说的Native方法)引用的对象
      • 在可达性分析算法中不可达的对象,仍有机会“自救”。一个对象真正被判断死亡,至少要经历两次标记过程。
        • 在可达性分析算法后发现没有与GC Roots 相连接的引用链,将会第一次被标记并且进行一次筛选,条件为是否有必要执行finalize()方法。
        • 如果对象没有覆盖这个方法,或者已经被虚拟机调用过了,则视为没有必要执行
        • 自救:只要在finalize()方法中重新与引用链上的任何一个对象建立关联即可

  2.什么时候进行GC

    • 可达性分析过程中必须保证一致性,也就是指在分析过程中,对象的引用关系不能发生改变,导致GC进行时,必须停顿所有Java执行线程。
    • 而当执行系统停顿下来之后,并不需要一个不漏地检查完所有执行上下文和全局的引用位置。使用一组称为OopMap的数据结构来记录哪些地方存放着对象引用。
    • 在类加载完成的时候,HotSpot就把对象内什么偏移量上是什么类型的数据计算出来,在JIT编译过程中,也会在特定的位置记录下栈和寄存器中哪些位置是引用。
    • 并不是什么地方都能停顿下来进行GC,只有到达安全点时才能暂停,那么如何让所有线程都到了最近的安全点再停顿下来呢?

      • 抢先式中断:不需要线程的执行代码主动配合,GC发生时,首先中断全部线程,再恢复不在安全点上的线程,让它跑到安全点上。
      • 主动式中断:当GC需要中断线程时,不直接对线程操作,而是仅仅简单设置一个标志,各个线程执行时,主动去轮询这个标志,发现标志为真时就主动中断挂起,而轮询标志的地方是与安全点重合的。
    • 安全点机制

      • 但是如果为每一条指令都生成对应的OopMap,那将会需要大量的额外空间,这样GC的空间成本将会变得很高。
      • 因此设置一个安全点机制,只有在达到安全点时才能暂停。既不能太少以致于让GC等待时间太长,也不能太过于频繁以至于过分增大运行时的负荷.
    • 安全区域机制
      • 使用安全点机制似乎已经完美解决了如何进入GC的问题,但是这个机制能保证程序执行时,在不太长的时间内就会遇到可进入GC的安全点,但是程序不执行的时候呢
      • 这个时候,就需要安全区域来解决了。安全区域是指在一段代码片段中,引用关系不会发生改变。在这个区域中的任意地方开始GC都是安全的。

  3.如何进行GC

    • 标记-清除算法

      • 首先标记出所有需要回收的对象,在标记完成后统一回收所有被标记的对象
      • 不足:
        • 效率问题,标记和清除两个过程的效率都不高,
        • 空间问题:标记清除之后会产生大量不连续的内存碎片,空间碎片太多可能会导致以后在程序运行过程中需要分配较大对象时,无法找到足够的连续内存而不得不提前出发另一次垃圾收集动作
    • 复制算法
      • 将可用内存容量划分为大小相等的两块,每次只使用其中的一块,当这一块的内存用完后,就将还存活者的对象复制到另一块上面,然后把已使用过的内存空间一次清理掉。
      • 这样使得每次都是对整个半区进行内存回收,内存分配时也就不用考虑内存碎片等复杂情况,只要移动堆顶指针。按顺序分配内存即可,实现简单,运行高效。
      • 问题:代价是将内存缩小为了原来的一半
      • 改进:
        • 目前商业虚拟机都采用这种收集算法来回收新生代,而研究表明,新生代中的对象98%是“朝生夕死”的,所以并不需要1:1的比例来划分。而是将内存分为一块较大的Eden空间和两块较小的Survivor空间。
        • 当回收时,将Eden和Survivor中还存活着的对象一次性地复制到另外一块Survivor空间上,最后清理Eden和刚才用过的Survivor空间
        • 这样只有10%的内存会被“浪费”
        • 当然当出现Survivor空间不够用时,需要依赖其他内存(这里只老年代)进行分配担保
    • 标记-整理算法
      • 标记过程仍然与“标记-清除”算法一样,但后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存
    • 分代收集算法
      • 根据对象存活周期的不同将内存划分为几块,一般是将java堆分为新生代和老年代,这样就可以根据每个年代的特点采用最适当的收集算法。
      • 在新生代中,每次垃圾收集都会有大批对象死去,只有少量存活,那就选用复制算法,只需要付出少量存活对象的复制成本就可以完成收集。
      • 而老年代因为对象的存活率较高,且没有额外空间对它进行担保,就必须使用标记-清除或者标记-整理算法来进行回收

GC的过程的更多相关文章

  1. 源码分析HotSpot GC过程(二):DefNewGeneration的GC过程

    由于虚拟机的分代实现,虚拟机不会考虑各个内存代如何实现垃圾回收,具体的工作(对象内存的分配也是一样)由各内存代根据垃圾回收策略自行实现. DefNewGeneration的使用复制算法进行回收.复制算 ...

  2. 不得不知的CLR中的GC

    引言 GC 作为CLR的垃圾回收器,让程序员可以把更多的关注度放在业务上而不是垃圾回收(内存回收)上.其实很多语言也有类似的东东, 如Java也有JIT 等等 GC基本概念 垃圾回收机制的算法有好多种 ...

  3. 《代码的未来》读书笔记:内存管理与GC那点事儿

    一.内存是有限的 近年来,我们的电脑内存都有好几个GB,也许你的电脑是4G,他的电脑是8G,公司服务器内存是32G或者64G.但是,无论内存容量有多大,总归不是无限的.实际上,随着内存容量的增加,软件 ...

  4. 触发Full GC执行的情况

    除直接调用System.gc外,触发Full GC执行的情况有如下四种. 1. 旧生代空间不足 旧生代空间只有在新生代对象转入及创建为大对象.大数组时才会出现不足的现象,当执行Full GC后空间仍然 ...

  5. C#的GC机制(来自网摘复制,未整理)

    第一个就是很多人用.Net写程序,会谈到托管这个概念.那么.Net所指的资源托管到底是什么意思,是相对于所有资源,还是只限于某一方面资源?很多人对此不是很了解,其实.Net所指的托管只是针对内存这一个 ...

  6. Android GC 那点事

    版权声明:本文由陈昱全原创文章,转载请注明出处: 文章原文链接:https://www.qcloud.com/community/article/170 来源:腾云阁 https://www.qclo ...

  7. 如何避免后台IO高负载造成的长时间JVM GC停顿(转)

    译者著:其实本文的中心意思非常简单,没有耐心的读者建议直接拉到最后看结论部分,有兴趣的读者可以详细阅读一下. 原文发表于Linkedin Engineering,作者 Zhenyun Zhuang是L ...

  8. GC学习笔记

    GC学习笔记 这是我公司同事的GC学习笔记,写得蛮详细的,由浅入深,循序渐进,让人一看就懂,特转到这里. 一.GC特性以及各种GC的选择 1.垃圾回收器的特性 2.对垃圾回收器的选择 2.1 连续 V ...

  9. GC之三--GC 触发Full GC执行的情况及应对策略

    1.System.gc()方法的调用 此方法的调用是建议JVM进行Full GC,虽然只是建议而非一定,但很多情况下它会触发 Full GC,从而增加Full GC的频率,也即增加了间歇性停顿的次数. ...

随机推荐

  1. 【集合】Java集合框架

    Java类库中帮助我们在程序设计中实现了传统的数据结构.本文章跳过理论部分,主要介绍如何使用标准库中的集合类. 1 将集合的接口与实现分离 Java集合类库将接口与实现分离.以队列为例: public ...

  2. ccf-炉石传说-201609-3

    大概是CCF 第三题比较简洁的一道题吧 尽量设计好一个数据结构: node t[2][10]: 存双方的英雄和随从 int    num[2]: 存隋朝的数量 用p来实现双方的切换,因为有统一 的接口 ...

  3. 20164322 韩玉婷-----Exp6 信息搜索与漏洞扫描

    1.实践目标 掌握信息搜集的最基础技能与常用工具的使用方法. 2.实践内容 (1)各种搜索技巧的应用 (2)DNS IP注册信息的查询 (3)基本的扫描技术:主机发现.端口扫描.OS及服务版本探测.具 ...

  4. webbug3.0靶场第二关

    由于是新手,当看见一个图片后一脸蒙比,查了一下才知道这原来叫做隐写术 看人家说破解图片隐写术用Stegsolve非常好用,然后查了一下kali软件仓库并没有找到Steegsolve这个软件,只能另想他 ...

  5. 前端AES解密

    使用插件Crypto.JS 安装 npm install --save_dev crypto-js // 导入 crypto-js 包 import CryptoJS from 'crypto-js/ ...

  6. Git学习之第一次使用PR

    发起PR的流程 1.Fork想要pr的项目,在自己的仓库里建立一个相同的项目. 2.Clone我们Fork的项目,在本地建立一个项目,方便修改. 3.将修改后的本地项目上传到github上. 4.向原 ...

  7. Taskctl安装及配置Kettle插件

    服务端安装 从官网下载服务端安装包(含字符客户端/代理组件) 1.环境变量设置 在fedora的终端下,输入sudo vi /etc/profile,将以下语句添加至文末 export TASKCTL ...

  8. 部署activiti 5.15.1的Activiti Explorer

    1.从官网下载activiti包,将其中的activiti-explorer.war文件拷贝到tomcat的webapps目录下: 2.将mysql驱动包文件mysql-connector-java- ...

  9. tunnel sw

    tunnel sw openssh vpn httprltunnel BarbaTunnel ngrok Chisel https://github.com/jpillora/chisel/blob/ ...

  10. java-同一用户顶替操作(session过期或无效)

    同一账号后者登录前者被强制退出:(可以通过监听器或过滤器进行监测session是否无效) 首先根据输入的用户名和密码做验证,通过验证查询用户信息.在用户信息不为空的前提下,比较静态变量中的sessio ...