Java虚拟机之GC
⑴背景
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的更多相关文章
- java虚拟机(十三)--GC调优思路
GC调优对我们开发人员来说,如果你想要技术方面一直发展下去,这部分内容的了解是必不可少的,jvm对于工作.面试来说都很重要,GC调优的问题 更是重中之重,因为是对你jvm学习内容的实践,知识只有应用实 ...
- java虚拟机之GC(转)
垃圾回收主要内容: 1. 那些内存需要回收? 2. 什么时候回收? 3. 如何回收? 垃圾回收主要针对运行时数据区那些区域? 运行时数据区的线程私有区域有:虚拟机栈,本地方法栈,程序计数器等: 栈中的 ...
- Java 虚拟机枚举 GC Roots 解析
JVM 堆内存模型镇楼. 读<深入理解 Java 虚拟机>第三章GC算法,关于 GC Roots 枚举的段落没说透彻,理解上遇到困惑.因此对这点进行扩展并记录,发现国内各种博客写来写去都是 ...
- java虚拟机(十一)--GC日志分析
GC相关:java虚拟机(六)--垃圾收集器和内存分配策略 java虚拟机(五)--垃圾回收机制GC 打印日志相关参数: -XX:+PrintGCDetails -XX:PrintGCTimestam ...
- 深入理解java虚拟机,GC参考手册
深入理解java虚拟机 一.<深入理解Java虚拟机> 1.第2章 Java内存区域与内存溢出异常 2.第3章 垃圾收集器与内存分配策略 3.第4章 虚拟机性能监控与故障处理工具 4.第5 ...
- Java虚拟机:GC算法深度解析
版权声明:本文为博主原创文章,转载请注明出处,欢迎交流学习! 在前面的文章里介绍了可达性分析算法,它为我们解决了判定哪些对象可以回收的问题,接下来就该我们的垃圾收集算法出场了.不同的垃圾收集算法有各自 ...
- 深入理解Java虚拟机,gc输出参数
https://blog.csdn.net/qq_21383435/article/details/80702205
- java虚拟机(十二)--可视化工具分析GC日志
在上篇博客中,我们学习了Parallel.CMS.G1三种垃圾收集器的日志格式,本次我们通过工具去分析日志,会更加的直观 日志格式博客地址:java虚拟机(十一)--GC日志分析 GCeasy: 这是 ...
- Java虚拟机-垃圾收集器
垃圾收集器(Garbage Collection, GC)的诞生引导出了三个问题: 哪些内存需要回收? 什么时候回收? 如何回收? 对于线程独占的三个区域(程序计数器.虚拟机栈.本地方法栈)不用过多的 ...
随机推荐
- Linux显示用户注册名
Linux显示用户注册名 youhaidong@youhaidong-ThinkPad-Edge-E545:~$ finger -s Login Name Tty Idle Login Time Of ...
- 常用javascript表单验证方法
//座机电话验证(支持分机) function chekeTel(tel) { var Tel = /^\d{3,4}-\d{7,8}(-\d{3,4})?$/; if (Tel.test(tel)) ...
- poi 导入导出的api说明(大全)
原文链接:http://www.cnblogs.com/qingruihappy/p/8443101.html poi 导入导出的api说明(大全) 一. POI简介 ApachePOI是Apache ...
- eval及json的理解
一,案例一 <br><br> 复制代码 var str = '{"name": "hanzichi", "age": ...
- freemarker中的substring取子串(十四)
freemarker中的substring取子串 1.substring取子串介绍 (1)表达式?substring(from,to) (2)当to为空时,默认的是字符串的长度 (3)from是第一个 ...
- 关系型数据库工作原理-查询优化器之数据访问方式(翻译自Coding-Geek文章)
本文翻译自Coding-Geek文章:< How does a relational database work>.原文链接:http://coding-geek.com/how-data ...
- NancyFX 第十一章 Bootstrapping
本章我们将深入Nancy的内部,对Nancy的内部组件进行修改和调整. 那什么是bootstrap哪?字典里是这么介绍的: 一般而言,处于引导中(bootstrapping)是在终端用户可以使用之前开 ...
- mysql 服务启动失败
mysql 数据库连接失败 1.用naviCat Preiumn 连接本地的mysql 失败,查找原因,mysql 数据库服务没有启用,但是在服务列表里面没有找到对应的mysql 服务. 所以在cmd ...
- C语言引用另一个源文件中定义的数组
C语言中是可以引用另外一个源文件的全局数组的,但是不能引用局部数组. 引用方式举例如下: 设a.c文件有有数据定义 int array1[10]; 现有b.c文件中想访问a.c中的array1数组 ...
- OCR技术浅探:基于深度学习和语言模型的印刷文字OCR系统
作者: 苏剑林 系列博文: 科学空间 OCR技术浅探:1. 全文简述 OCR技术浅探:2. 背景与假设 OCR技术浅探:3. 特征提取(1) OCR技术浅探:3. 特征提取(2) OCR技术浅探:4. ...