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

回收机制:

  现在的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. MySQL 性能优化的最佳20多条经验分享(收藏)

    1. 为查询缓存优化你的查询 大多数的MySQL服务器都开启了查询缓存.这是提高性最有效的方法之一,而且这是被MySQL的数据库引擎处理的.当有很多相同的查询被执行了多次的时候,这些查询结果会被放到一 ...

  2. js★★★【面向对象的使用方法】*****************★★★★ 相当重要

    标准用法: function Sprite(){ //函数内容部设置属性 this.name='shimily'; } //原型上设置方法 Sprite.prototype.show=function ...

  3. Spring源码学习(5)—— bean的加载 part 2

    之前归纳了从spring容器的缓存中直接获取bean的情况,接下来就需要从头开始bean的加载过程了.这里着重看单例的bean的加载 if(ex1.isSingleton()) { sharedIns ...

  4. jQuery常用 遍历函数

    jQuery 遍历函数包括了用于筛选.查找和串联元素的方法.本文主要介绍日常工作中常用的JQ遍历,帮助一下初学者快速的接触遍历函数,提高自己的代码编写速度,写出更简洁更实用的代码,祝前端的同学们,在前 ...

  5. js 获取字符串中所有的数字和汉字

    var re1 = /(\d{1,3})+(?:\.\d+)?/g var re2 = /[\u4e00-\u9fa5]{2,}/g var str="11我22们33两个"; v ...

  6. unsigned long long类型与long long类型

    最近做题的时候,经常遇到范围是2^63,取模2^64的这种题目.遇到这种限制条件时就要想到用unsigned long long类型. 可以简洁地声明为typedef unsigned long lo ...

  7. SpringBoot项目如何打War包

    首先,需要添加Tomcat启动依赖 <dependency> <groupId>org.springframework.boot</groupId> <art ...

  8. foreach 使用 引用& $value . 使用 unset($value)

    1.知识点: 2. 例子 2.1 例子1 . $arr 引用循环, 赋值变量是 &$v ,第一个循环使用后 ,没有 使用unset($v) , $arr2 正常循环, 赋值变量是 $v ,  ...

  9. like 内容转义

    如题,当SQL语句中使用Like查询,且期望匹配的结果中含有"\"的,应当把"\"替换为"\\\\". 比如数据库中text字段有以下三行: ...

  10. datetime模块

    # 其中days = -2,可以根据需要进行替换,这样就可以得到不同需要的日期了. # # 另外:可以通过strftime方法,指定时间的输出格式. # # 除了以上输入的   %Y-%m-%d    ...