⑴背景

Java堆和方法区实现类所需内存是不一样的,每个方法的多分支需要的内存也可能不一样,我们只有在运行期间才能制动创建哪些对象。这部分内存分配与回收都是动态的,而垃圾回收器所关注的就是这些这部分内存。

⑵基本垃圾回收算法

①引用计数法:给每个对象添加一个引用计数器,每当有一个地方引用它时,计数器值就加1,当引用失效时,计数器就减1,任何时刻计数器为0的对象是不可能被使用的。

引用计数法简单易实现,但判定效率也很高,在大部分情况下式不错的算法。但主流Java虚拟机都没有使用引用计数器来管理内存,主要原因是他很难解决对象之间的循环引用问题

例如:ObjA.instance = ObjB,ObjB.instance = ObjA,除此之外这两个对象再无其他引用。实际上这两个对象没有别其他对象应用,但是引用计数器无法通知GC来回收它们。

②可达性分析:在Java中是使用可达性分析来判定对象是否存活。算法思路就是通过一系列称为“GC Roots”的队形作为起点,从这些节点向下搜索搜索所走的路径称为“引用链”,当一个对象

到GC Roots没有任何引用链相连时,则证明此对象是不可用的。

如图:

③标记-清除算法:标记-清楚算法分为两个阶段,首先标记处所需的回收对象,在标记完成之后统一回收所有标记的对象,后面的算法都是基于该算法进行改进。该算法有两大不足之处:一是效率低,标记与清除的两个过程效率不高;二是空间问题,标记清除之后会产生大量的不连续内存碎片,空间碎片过多会导致以后程序运行时需要分配较大对象时,无法找到足够的连续内存,而不得不提前触发一次垃圾收集动作。

如图(图片来自网络):

④复制算法:复制算法常用于新生代。将可用内存按容量划分为大小相等的两块,每次使用其中一块,当这一块用完之后,仍存活的对象赋值到另一块上,然后再把已使用过的内存空间一次清理掉。这样使得每次都是对整个搬去进行内存回收,内存分配时不需要考虑内存不连续,碎片的情况,只需要按顺序分配内存即可。但是该算法的代价是内存缩小为原来的一半。属于用空间换时间。

在新生代的对象中98%是“朝生夕死”的,所以并不需要按照1:1的比例划分空间,而是将内存分为一块较大的Eden空间和两块较小的Suvivor空间,每次使用Eden和其中一个Survivor,当回收时,将Eden和Suvivor中还存活的对象一次性地复制到另一块Survivor空间上,然后清楚掉Eden和刚才用过的Survivor空间。

⑤标记-整理:标记-整理算法常用于老年代,如果在内存中如果对象的存活率较高,使用复制算法效率就会非常低下。于是根据老年代的特点出现了“标记-整理”算法,其标记过程与“标记-清除”算法一样,后续步骤不是直接就对可回收对象进行清除,而是让所有存活的对象移动到一端,然后直接清理掉边界以外的内存。

如图(图片来自网络):

⑥分代收集算法:根据对象存活周期分为新生代和老年代,然后根据各自年代特点使用不同算法。在新生代中,每次垃圾收集时发现有大批对象死去,存货量较小,这时候使用复制算法就非常合适。在老年代中,对象的存活率较高,使用复制算法显然不划算,这时候就选择采用“”“标记-整理”算法去实现内存回收。

⑶垃圾收集器

HotSpot虚拟机垃圾收集器(图片来自网络)

①Serial收集器:该收集器是一个单线程的收集器,只会使用一个CPU或一条收集线程去完成垃圾收集,而且在进行垃圾收集时,其他工作线程都必须暂停。

②ParNew收集器:ParNew是Serial收集器的多线程版本。

ParNew收集器是Server模式下的虚拟机中首选的新生代收集器,其中一个与性能无关但很重要的原因是,除了Serial收集器外,目前只有它能够与CMS收集器配合工作,在单CPU环境中效果不比Serial,但但当CPU非常多的环境下,ParNew的优势就体现出来了。

③ CMS收集器:以获取最短回收停顿时间为目标的收集器,CMS收集器基于“标记-清除”算法实现。

过程分为4个部分:

Ⅰ 初始标记:初始标记仅仅只是标记GC Roots所能够关联到的对象(可达性分析)

Ⅱ 并发标记:根搜索(GC Roots Tracing)算法基本原理是:GCRoot对象作为起始点(根)。如果从根到某个对象是可达的,则该对象称为“可达对象”(存活对象,不可回收对象)。

Ⅲ 重新标记:重新标记阶段是为了修正并发标记期间因用户程序运作而导致标记产生变动的那一部分对象的标记记录。(边打扫卫生边仍纸屑)

Ⅳ 并发清除:并发将可回收内存全部回收。

其中需要“Stop The World”的有Ⅰ,Ⅲ过程

CMS缺点:

Ⅰ.CPU资源非常敏感,在面向并发程序时,CMS虽然不会导致用户线程停顿,但仍然会因为并发标记或并发清除占用了部分线程,导致应用程序变慢,总吞吐量降低。

Ⅱ.CMS无法处理浮动垃圾,由于CMS并发清理阶段用户线程仍在运行着,伴随程序运行,自然还会有新的垃圾不断产生,这一部分垃圾出现在标记标记过程之后,CMS无法在当次集中处理它们,只能留到下一次GC再处理.

Ⅲ.CMS基于“标记-清除”算法,该算法会产生大量的空间碎片,会出现老年代空间剩余,但无法找到连续的空间去分配当前对象,就必须提前触发一次Full GC.

④G1收集器:G1收集器是目前前沿收集器技术之一,到了JDK7u4才达到了商用程度

G1收集器所具备的特点:

Ⅰ.并发与并行:G1具有CMS一样多线程操作能力,G1能利用多CPU、多核环境下的硬件优势,使用多个CPU来缩短Stop-The-World停顿时间,部分其他收集器原本需要停顿Java线程执行的GC动作,G1收集器仍然能够通过并发方式让Java线程继续执行。

Ⅱ.分代收集:G1不需要其他收集器配合就能够独立管理整个GC堆,但他能够使用不同的方式去处理新创建对象和已存活一段时间对象、熬过多次的旧对象都有自己的处理方法。

Ⅲ.空间整合:CMS基于“标记-清除”,缺点是出现许多不连续内存,而G1则基于“标记-整理”,从局部(两个Region)上看基于“复制”算法,G1运行期间不会产生大量空间碎片,收集后能提供规整的可用内存空间,在分配大对象时不会由于找不到可用的连续内存而出发下一次GC。

Ⅳ.可预测停顿:G1与CMS不同,G1除了追求低停顿以外,还能建立可预测的停顿时间模型。

更详细:http://blog.csdn.net/renfufei/article/details/41897113

Java虚拟机之GC的更多相关文章

  1. java虚拟机(十三)--GC调优思路

    GC调优对我们开发人员来说,如果你想要技术方面一直发展下去,这部分内容的了解是必不可少的,jvm对于工作.面试来说都很重要,GC调优的问题 更是重中之重,因为是对你jvm学习内容的实践,知识只有应用实 ...

  2. java虚拟机之GC(转)

    垃圾回收主要内容: 1. 那些内存需要回收? 2. 什么时候回收? 3. 如何回收? 垃圾回收主要针对运行时数据区那些区域? 运行时数据区的线程私有区域有:虚拟机栈,本地方法栈,程序计数器等: 栈中的 ...

  3. Java 虚拟机枚举 GC Roots 解析

    JVM 堆内存模型镇楼. 读<深入理解 Java 虚拟机>第三章GC算法,关于 GC Roots 枚举的段落没说透彻,理解上遇到困惑.因此对这点进行扩展并记录,发现国内各种博客写来写去都是 ...

  4. java虚拟机(十一)--GC日志分析

    GC相关:java虚拟机(六)--垃圾收集器和内存分配策略 java虚拟机(五)--垃圾回收机制GC 打印日志相关参数: -XX:+PrintGCDetails -XX:PrintGCTimestam ...

  5. 深入理解java虚拟机,GC参考手册

    深入理解java虚拟机 一.<深入理解Java虚拟机> 1.第2章 Java内存区域与内存溢出异常 2.第3章 垃圾收集器与内存分配策略 3.第4章 虚拟机性能监控与故障处理工具 4.第5 ...

  6. Java虚拟机:GC算法深度解析

    版权声明:本文为博主原创文章,转载请注明出处,欢迎交流学习! 在前面的文章里介绍了可达性分析算法,它为我们解决了判定哪些对象可以回收的问题,接下来就该我们的垃圾收集算法出场了.不同的垃圾收集算法有各自 ...

  7. 深入理解Java虚拟机,gc输出参数

    https://blog.csdn.net/qq_21383435/article/details/80702205

  8. java虚拟机(十二)--可视化工具分析GC日志

    在上篇博客中,我们学习了Parallel.CMS.G1三种垃圾收集器的日志格式,本次我们通过工具去分析日志,会更加的直观 日志格式博客地址:java虚拟机(十一)--GC日志分析 GCeasy: 这是 ...

  9. Java虚拟机-垃圾收集器

    垃圾收集器(Garbage Collection, GC)的诞生引导出了三个问题: 哪些内存需要回收? 什么时候回收? 如何回收? 对于线程独占的三个区域(程序计数器.虚拟机栈.本地方法栈)不用过多的 ...

随机推荐

  1. 【转】MySQL乐观锁在分布式场景下的实践

    背景 在电商购物的场景下,当我们点击购物时,后端服务就会对相应的商品进行减库存操作.在单实例部署的情况,我们可以简单地使用JVM提供的锁机制对减库存操作进行加锁,防止多个用户同时点击购买后导致的库存不 ...

  2. 【NFS】nfs安装调优

    nfs [root@flymaster ~]# rpm -qa nfs-utils rpcbindnfs-utils-1.2.3-75.el6.x86_64rpcbind-0.2.0-13.el6_9 ...

  3. VMware下载安装及CentOS7下载安装

    我是在Windows10系统下,下载的VMware Workstation 12 1.下载虚拟机软件 安装包位置(里面有激活码):https://pan.baidu.com/s/1i5hn5lj 2. ...

  4. Mybatis常见面试题

    Mybatis常见面试题 #{}和${}的区别是什么? #{}和${}的区别是什么? 在Mybatis中,有两种占位符 #{}解析传递进来的参数数据 ${}对传递进来的参数原样拼接在SQL中 #{}是 ...

  5. C#总结(六)EventBus事件总线的使用-自己实现事件总线

    在C#中,我们可以在一个类中定义自己的事件,而其他的类可以订阅该事件,当某些事情发生时,可以通知到该类.这对于桌面应用或者独立的windows服务来说是非常有用的.但对于一个web应用来说是有点问题的 ...

  6. 总结各类错误(always online)

    最近发现打暴力(还有梦想中的正解)都会打错,决定好好总结一下各种坑比错误QAQ 1.一定要好好看数据范围,接近int类型上限,如果要求和,一定要开long long并且改大你的inf值(TAT暴力分流 ...

  7. enable_shared_from_this类的作用和实现

    使用举例 实际中, 经常需要在一个被shared_ptr管理的对象的内部获取自己的shared_ptr. 比如: 通过this指针来构造一个shared_ptr, 如下: struct Bad { v ...

  8. Android端 高德地图点击得到经纬度

    <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android=&q ...

  9. 平衡树(Splay)模板

    支持区间操作. 单点操作和区间操作分开使用,需要一起使用需要部分修改. 对应题目FJUTOJ2490 #include<cstdio> #include<cstring> #i ...

  10. BZOJ1493 NOI2007 项链工厂 线段树模拟

    提交地址:http://www.lydsy.com/JudgeOnline/problem.php?id=1493 题目大意:给一个数列,进行一系列操作.包括旋转,翻转,改变等操作,以及查询颜色段数. ...