垃圾收集主要是针对堆和方法区进行。

回收机制:

  现在的JVM基本都使用分代回收机制,把堆中内存区域分为新生代,老年代。

  新生代:

Eden(80%) Survivor0(10%) Survivor1(10%)

  老年代:

Old place

  

  回收算法:

    Minor GC:发生在新生代,内存空间小,频繁执行,所以一般执行速度很快。

    Full GC(Major GC):Major GC发生在老年代,一般会伴随着一次Minor GC,所以也叫Full GC,一般执行速度较慢。

    

    在新生代中采用复制算法,每个新对象都最先在Eden里,当Eden满了之后(此时两个Survivor都为空),将触发一次Minor GC,Eden里存活的对象就会送到Survivor0中,即 Eden→Survivor0,Eden里对象清空。

  下一次Eden区满之后,就将Eden和Survivor0中存活的对象放到Survivor1中,即Eden+Survivor0→Survivor1。下次Eden满了之后,Eden+Survivor1→Survivor0..........................

  如此循环,当对象的复制次数达到16次时,对象就会被送到老年代。

    当新生代中对象放入老年代,而老年代中空间不足时,将会进行Full GC。

    

为什么需要Survivor,又为什么需要两个呢?

  先假设没有Survivor:

    Eden中的对象经历Minor GC后送到Old place,因为Minor GC很频繁,那么Old place很快就被填满了,然后进行Full GC,然而Full GC很消耗时间,会影响程序的执行速度和响应速度。

    若增大Old place的空间,虽然Full GC的频率降低了,但是每次Full GC的时间增长了。若减小Old place的空间,Full GC的时间减少,但是频率增加了。

    由此可见,增加Survivor的作用是,减少送往老年代的对象,从而降低Full GC的频率。

  再假设只有一个Survivor:

    Eden中的对象经历Minor GC后送到空的Survivor,此时没有什么问题,再然后又经历Minor GC,此时Survivor中有些对象死亡,而新的对象从Eden中过来,就出现了碎片化的问题。

    

    由此可见,加一个Survivor是不可取的,至少的加两个,那为什么不三个四个呢?我觉得可能是因为新生代和老年代的空间大小比例有关,若增加多了Survivor,则会降低老年代的利用率,所以选择了两个Survivor。

    所以设置两个Survivor的原因就是,解决碎片化。

回收器:

  新生代:

      Serial回收器:

        串行回收器,Client 模式下的默认新生代收集器,是一个单线程的回收器,所以对于只有一个CPU来说,利用率最高。

      ParNew回收器:

        并行回收器,Server 模式下的虚拟机首选新生代收集器,能与CMS回收器配合,是多线程版的Serial,默认开启线程数量与CPU核数相同,可以使用 -XX:ParallelGCThreads 参数来设置线程数。

      Parallel Scavenge回收器:

        同样是多线程,但是其余回收器都是以缩短“垃圾回收时间”为主,而Parallel Scavenge的目标是达到一个可控制的吞吐量,它被称为“吞吐量优先”收集器。这里的吞吐量指 CPU 用于运行用户代码的时间占总时间的比值。

        停顿时间越短就越适合需要与用户交互的程序,良好的响应速度能提升用户体验。而高吞吐量则可以高效率地利用 CPU 时间,尽快完成程序的运算任务,适合在后台运算而不需要太多交互的任务。

  老年代:

      Serial Old回收器:

        同Serial回收器。

      Parallel Old回收器:

        同Parallel Scavenge回收器。

      CMS回收器:

        CMS是Concurrent(同时发生的)- Mark(标记)- Sweep(清理),所以此回收器采用标记-清理算法。分为以下四个步骤:  

        1、初始标记:仅仅只是标记一下 GC Roots 能直接关联到的对象,速度很快,需要停顿。

        2、并发标记:进行 GC Roots Tracing 的过程,它在整个回收过程中耗时最长,不需要停顿。

        3、重新标记:为了修正并发标记期间因用户程序继续运作而导致标记产生变动的那一部分对象的标记记录,需要停顿。

        4、并发清除:不需要停顿。

        在整个过程中耗时最长的并发标记和并发清除过程中,收集器线程都可以与用户线程一起工作,不需要进行停顿。

  G1回收器:

    G1(Garbage-First),它是一款面向服务端应用的垃圾收集器,在多 CPU 和大内存的场景下有很好的性能。HotSpot 开发团队赋予它的使命是未来可以替换掉 CMS 收集器。

  堆被分为新生代和老年代,其它收集器进行收集的范围都是整个新生代或者老年代,而 G1 可以直接对新生代和老年代一起回收。

   参考资料:

      1、JVM GC 机制与性能优化

      2、为什么新生代内存需要有两个Survivor区

      3、Java虚拟机

JVM GC机制的更多相关文章

  1. JVM GC 机制与性能优化

    目录(?)[+] 1 背景介绍 与C/C++相比,JAVA并不要求我们去人为编写代码进行内存回收和垃圾清理.JAVA提供了垃圾回收器(garbage collector)来自动检测对象的作用域),可自 ...

  2. 理解JVM GC

    理解JVM GC对于我们把控Java应用有很大的帮助.下面我从运维角度,把网上的JVM相关的资料整理如下,以加深对JVM GC的理解.如有错误的地方,请看官指正. JVM内存使用分类 JVM的内存分区 ...

  3. 直击面试,聊聊 GC 机制

    前言 文章来源:https://studyidea.cn/ GC 中文直译垃圾回收,是一种回收内存空间避免内存泄漏的机制.当 JVM 内存紧张,通过执行 GC 有效回收内存,转而分配给新对象从而实现内 ...

  4. 聊聊面试中常问的GC机制

    GC 中文直译垃圾回收,是一种回收内存空间避免内存泄漏的机制.当 JVM 内存紧张,通过执行 GC 有效回收内存,转而分配给新对象从而实现内存的再利用. JVM GC 机制虽然无需开发主动参与,减轻不 ...

  5. 【转载】Java性能优化之JVM GC(垃圾回收机制)

    文章来源:https://zhuanlan.zhihu.com/p/25539690 Java的性能优化,整理出一篇文章,供以后温故知新. JVM GC(垃圾回收机制) 在学习Java GC 之前,我 ...

  6. JVM的 GC机制和内存管理

    GC机制:java垃圾回收机制,垃圾收集器线程(Garbage Collection Thread)在 JVM 处于空闲循环式,会自动回收无用的内存块. 垃圾收集算法:1.引用计数  2.根搜索  3 ...

  7. JVM内存管理及GC机制

    一.概述 Java GC(Garbage Collection,垃圾收集,垃圾回收)机制,是Java与C++/C的主要区别之一,作为Java开发者,一般不需要专门编写内存回收和垃圾清理代码,对内存泄露 ...

  8. 深入JVM系列(二)之GC机制、收集器与GC调优

    一.回想JVM内存分配 须要了解很多其它内存模式与内存分配的,请看 深入JVM系列(一)之内存模型与内存分配 1.1.内存分配: 1.对象优先在EDEN分配 2.大对象直接进入老年代  3.长期存活的 ...

  9. Java性能优化之JVM GC(垃圾回收机制)

    Java的性能优化,整理出一篇文章,供以后温故知新. JVM GC(垃圾回收机制) 在学习Java GC 之前,我们需要记住一个单词:stop-the-world .它会在任何一种GC算法中发生.st ...

随机推荐

  1. font-family 中文字体列表

    华文细黑:STHeiti Light [STXihei] 华文黑体:STHeiti 华文楷体:STKaiti 华文宋体:STSong 华文仿宋:STFangsong 儷黑 Pro:LiHei Pro ...

  2. 第十四周翻译-《Pro SQL Server Internals, 2nd edition》

    <Pro SQL Server Internals, 2nd edition> 作者:Dmitri Korotkevitch 翻译:赖慧芳 译文: 设计和优化索引 定义一种应用于所有地方的 ...

  3. socket.io 实现简易聊天

    客户端: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF- ...

  4. web项目中web.xml简介

    什么是 XML? XML 指可扩展标记语言(EXtensible Markup Language) XML 是一种标记语言,很类似 HTML XML 的设计宗旨是传输数据,而非显示数据 XML 标签没 ...

  5. 用 Cobertura 测量测试覆盖率

      尽管测试先行编程(test-first programming)和单元测试已不能算是新概念,但测试驱动的开发仍然是过去 10 年中最重要的编程创新.最好的一些编程人员在过去半个世纪中一直在使用这些 ...

  6. docker配置代理的用户名密码

    公司访问外网全部需要经过代理服务器,在使用docker的过程中,发现就算为docker配置了代理,还是会因为没有代理服务器认证,导致pull操作失败,报如下错误: Error response fro ...

  7. json&pickle模块

    序列化:我们把对象(变量)从内存中变成可存储或传输的过程称之为序列化 反序列化:把变量内容从序列化的对象重新读到内存中,这一过程称为反序列化 为什么要序列化? 1.持久保存状态 一个软件的执行就是在处 ...

  8. [转载]Fiddler 解析!抓包抓得好真的可以为所欲为 [一]

    说起抓包,很多人以为就是用个工具,简简单单地抓一下就可以了.昨天在面试一个安卓逆向,直接告诉我[抓包没有技术含量].在这里,我必须发一个教程,解析一下抓包神器——Fiddler.Fiddler仅仅是一 ...

  9. 转载 * jQuery实现动态分割div—通过拖动分隔栏实现上下、左右动态改变左右、上下两个相邻div的大小

    由jQuery实现上下.左右动态改变左右.上下两个div的大小,需要自己引入jquery1.8.0.min.js包 可用于页面布局. //============================ind ...

  10. SpringBoot统一异常处理

    /** * 异常处理器 */ @RestControllerAdvice // public class BDExceptionHandler { private Logger logger = Lo ...