目前没有完美的收集器,不同的厂商、版本的虚拟机提供的垃圾收集器会有很大的差别,用户根据自己应用特点和要求组合出各个年代所使用

的收集器。基于jdk1.7Update14之后的虚拟机。

HotSpot的垃圾收集器

上图是作用于新生代和老年代的收集器,连线代表可以搭配使用。

新生代采用复制算法,而老年代采用标记-整理、标记-清除算法

1、Serial:串行

  采用复制算法的单线程收集器,进行GC的时候需要暂停其他线程的工作(被称为Stop The World),直到它收集结束。Serial依然是运行在

Client模式下的默认新生代收集器,因为简单、高效。用户桌面应用场景中,分配给虚拟机管理的内存一般来说不会很大,收集几十兆甚至一两百

兆的新生代停顿时间在几十毫秒最多一百毫秒,只要不是频繁发生,这点停顿是完全可以接受的。单个CPU环境下比较适合。

2、ParNew

  ParNew收集器其实就是Serial收集器的多线程版本,除了使用多条线程进行垃圾收集外,其余行为和Serial收集器完全一样,一些参数和回收策

略都相同。它是Server模式下的首选的新生代收集器,因为除了Serial收集器外,目前只有它能与CMS收集器配合工作。它默认开启的收集线程数与

CPU数量相同,在CPU数量非常多的情况下,可以使用-XX:ParallelGCThreads参数来限制垃圾收集的线程数。

3、Parallel Scavenge

  新生代,用复制算法,并行的多线程收集器,CMS等收集器的关注点是尽可能缩短垃圾收集时用户线程的停顿时间,而Parallel收集器的目标则

是打到一个可控制的吞吐量。吞吐量=CPU用于运行用户代码时间/CPU总消耗时间的比值,即吞吐量=运行用户代码时间/(运行用户代码时间+垃圾

收集时间)。另外,Parallel收集器是虚拟机运行在Server模式下的默认垃圾收集器。

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

后台运算而不需要太多交互的任务。

4、Serial Old

  Serial收集器的老年代版本,同样是一个单线程收集器,使用“标记-整理算法”,这个收集器的主要意义也是在于给Client模式下的虚拟机使用。

5、Parallel Old

  Parallel收集器的老年代版本,使用多线程和“标记-整理”算法。这个收集器在JDK 1.6之后的出现,“吞吐量优先收集器”终于有了比较名副

其实的应用组合,在注重吞吐量以及CPU资源敏感的场合,都可以优先考虑Parallel收集器+Parallel Old收集器的组合。

6、CMS:Concurrent Mark Sweep 非常适用B/S系统

  以获取最短GC停顿时间为目标的老年代收集器。目前很大一部分Java应用集中在互联网站或者B/S系统的服务端上,注重服务的响应速度,希望系

统停顿时间最短,以给用户带来较好的体验,CMS收集器就非常符合这类应用的需求。CMS收集器基于“标记-清除”算法实现的。

运行过程分为四步:

  初始标记:会有GC停顿,只是标记一下具有可达性的对象,速度很快

  并发标记:进行GC Roots Tracing的过程

  重新标记:会有GC停顿,修正并发标记期间标记产生变动的那部分对象的标记

  并发清除:

  并发标记、并发清除是耗时最长的但是可以与用户线程同时工作

缺点:

  1、占用CPU资源,应用程序吞吐量下降

  2、并发清理阶段用户线程还在运行,就会产生浮动垃圾,由于标记过了,只能下次GC才能清理

  3、采用"标记-清除"算法就会产生大量空间碎片,大对象分配很麻烦,可能提前Full GC

7、G1(Garbage-First):兼顾吞吐量和停顿时间的GC实现,是JDK9以后的默认GC选项

  JDK 7 Update 4后开始进入商用。使用G1收集器时,Java堆的内存布局就与其他收集器有很大差别,它将整个Java堆分为多个大小相等的独立

区域(Region),虽然还保留有新生代和老年代的概念,但新生代和老年代不再是物理隔离的了,它们都是一部分Region的集合。G1收集器跟踪各

个Region里面的垃圾堆积的价值大小,在后台维护一个优先列表,每次根据允许的收集时间,优先回收价值最大的Region(这也是Garbage-First

名称的由来)。这种使用Region划分内存空间以及有优先级的区域回收方式,保证了G1收集器在有限的时间内可以获取尽可能高的收集效率。

与其他GC收集器相比,G1的特点:

1).并发与并行

  充分利用多CPU、多核环境下的硬件优势,来缩短Stop-The-World停顿时间,G1可以通过并发让java程序继续执行

2).分带收集

  通过不同的方式处理新创建的对象和存货了一段时间、熬过多次GC的就对象来获取更好的收集效果

3).空间整合

  G1从整体来看基于“标记-整理”算法实现的收集器,从局部(两个Region之间)看基于“复制”算法实现

而且这两种算法不会产生内存空间碎片,收集后能提供规整的可用内存

4).可预测的停顿

  G1处理追求低停顿,还能建立可预测的停顿时间模型,让使用者明确指定在一个长度为Mms的时间片段内,消耗在GC的时间不超过Nms,几乎已经是实时Java的垃圾收集器的特征了。

  Region之间对象引用以及其他收集器中的新声代和老年代之间的对象引用,虚拟机都是使用Rememberd Set来避免全堆扫描。

如果不计算维护Rememberd Set的操作,收集步骤如下:

  1).初始标记

  2).并发标记

  3).最终标记

  4).筛选回收

GC日志:

DefNew:default new generation

PSYoungGen:Parallel Scavenge generation

ParNew:Parallel New Generation

老年代和永久带同理,名称也是由收集器决定

说明:

最前面的数字代表GC发生的时间,jvm启动经过的秒数

Full GC 证明这次GC发生了GC停顿,如果是调用了system.gc(),就会显示Full GC(system)

[PSYoungGen: 33280K->2415K(38400K)] 33280K->2423K(125952K), 0.0109733 secs]

33280K->2415K(38400K):GC前该内存区域已使用容量->GC后。。。。(该内存区域总容量)

33280K->2423K(125952K):堆的容量

0.0109733 secs:GC时间

[Times: user=0.02 sys=0.00, real=0.01 secs] :分别代表用户态消耗的CPU时间、内核态消耗的CPU时间、操作从开始到结束经过的墙钟事件

CPU时间和墙钟时间区别:

墙钟时间包含多种非运算的等待耗时,例如等待磁盘IO、等待线程阻塞

CPU时间不包含这些耗时,多CPU或多核,会叠加这些CPU时间

Minor GC 对年轻代进行回收,

Major GC 是清理老年代。

Full GC 是清理整个堆空间—包括年轻代和老年代。

Minor GC触发条件:当Eden区满时,触发Minor GC。

Full GC触发条件:

(1)调用System.gc时,系统建议执行Full GC,但是不是必然执行

(2)老年代空间不足

(3)方法区空间不足

(4)通过Minor GC后进入老年代的平均大小大于老年代的可用内存

(5)由Eden区、From Space区向To Space区复制时,对象大小大于To Space可用内存,则把该对象转存到老年代,且老年代的可用内存小于该对

象大小

内存分配与回收策略:内存分配的规则取决于使用的是哪一种垃圾回收收集器组合,还有虚拟机中与内存相关参数的配置

1、对象优先Eden space分配,如果Eden Space没有足够的空间,会发生一次Minor GC

2、大对象(很长的字符串、数组)直接分配得到老年代,通过参数-XX:PretenureSizeThreshold=3145728(3M),只要大于这个值,对象直接分

配到老年代,防止新生代进行大量内存复制

3、长时间存活的对象,会转到老年代,每个对象有个年龄计数器,在survivor每次经过一次Minor GC,就会加一,默认15的时候,会分到老年代

4、第三条不是绝对的,VM会动态判断

如果Survivor空间中相同年龄所有对象大小的综合大于Survivor空间的一半,年龄大于或等于该年龄的对象就可以直接进入老年代,无须等到

MaxTenuringThreshold要求的年龄

空间担保失败

  发生Minor GC之前,虚拟机会检查老年代最大可用的连续空间是否大于新生代所有对象总空间,如果成立,可以确保Minor GC是安全的,else

检查HandlerPromotionFailure设置值是否允许担保失败。if允许,继续检查老年代最大可用的连续空间是否大于历次晋升到老年代对象的平均大小

,true,查实进行一次Minor GC,尽管有风险,如果小于,或者参数设置不允许,改为进行一次Full GC但是HandlerPromotionFailure在jdk 6

Update 24没有作用了,jdk规则变成只要老年代的连续空间大于新生代对象总大小或者历次晋升的平均大小就会进行Minor GC,否则进行Full GC

java虚拟机(六)--垃圾收集器和内存分配策略的更多相关文章

  1. 深入JAVA虚拟机笔记-垃圾收集器与内存分配策略

    第三章:垃圾收集器与内存分配 问题:1.哪些内存需要回收 2.什么时候回收 3.怎么回收 回收方法区:

  2. 深入理解Java虚拟机:垃圾收集器与内存分配策略

    目录 3.2 对象已死吗 判断一个对象是否可被回收 引用类型 finalize() 回收方法区 3.3. 垃圾收集算法 1.Mark-Sweep(标记-清除)算法 2.Copying(复制)算法 3. ...

  3. 《深入理解Java虚拟机》——垃圾收集器与内存分配策略

    GC需要完成: 哪些内存需要回收 什么时候回收 如何回收 如何确定对象不再使用 引用计数算法 给对象添加一个引用计数器,当有一个地方引用它时,计数器值进行加1操作:当引用失效时,计数器值进行减1操作: ...

  4. 深入理解Java虚拟机笔记——垃圾收集器与内存分配策略

    目录 判断对象是否死亡 引用计数器算法 可达性分析算法 各种引用 回收方法区 垃圾收集算法 标记-清除算法 复制算法 标记-整理算法 分代收集算法 HotSpot算法实现 枚举根节点 GC停顿(Sto ...

  5. 深入理解java虚拟机(3)垃圾收集器与内存分配策略

    一.根搜索算法: (1)定义:通过一系列名为"GC Roots"的对象作为起点,从这些起点开始向下搜索,搜索走过的路径称为引用链,当一个对象到GC Roots没有任何引用链相连的时 ...

  6. java虚拟机学习-JVM内存管理:深入垃圾收集器与内存分配策略(4)

    Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的高墙,墙外面的人想进去,墙里面的人却想出来. 概述: 说起垃圾收集(Garbage Collection,下文简称GC),大部分人都把这项 ...

  7. 深入理解java虚拟机_第三章(上)----->垃圾收集器与内存分配策略

    1.  前言 这一版块内容比较多,分为两篇文章来做笔记.本文讲述上半部分垃圾收集部分;下一篇文章写内存分配部分. 概述 对象已死吗? 引用技术算法 可达性分析算法 再谈引用 两次标记 回收方法区 2. ...

  8. 深入理解java虚拟机----->垃圾收集器与内存分配策略(下)

    1.  前言 内存分配与回收策略 JVM堆的结构分析(新生代.老年代.永久代) 对象优先在Eden分配 大对象直接进入老年代 长期存活的对象将进入老年代 动态对象年龄判定 空间分配担保  2.  垃圾 ...

  9. 《深入java虚拟机》读书笔记之垃圾收集器与内存分配策略

    前言 该读书笔记用于记录在学习<深入理解Java虚拟机--JVM高级特性与最佳实践>一书中的一些重要知识点,对其中的部分内容进行归纳,或者是对其中不明白的地方做一些注释.主要是方便之后进行 ...

随机推荐

  1. sdut 4-1 复数类的运算符重载

    4-1 复数类的运算符重载 Time Limit: 1000MS Memory limit: 65536K 题目描写叙述 通过本题目的练习能够掌握成员运算符重载及友元运算符重载 要求定义一个复数类.重 ...

  2. mysql_connect 等待时间长,修改连接地址为127.0.0.1即可

    程序搬家后,运行非常慢分析流程: 1.外网的等待时间太长 2.内容等待时间也很长 3.断点查到仅仅一句 mysql_connect ("localhost",***,***)就要1 ...

  3. where 1=1影响效率以及having和where的区别

    低效的“WHERE 1=1” 网上有不少人提出过类似的问题:“看到有人写了WHERE 1=1这样的SQL,到底是什么意 思?”. 其实使用这种用法的开发人员一般都是在使用动态组装的SQL. 让我们想像 ...

  4. [ACM]2013山东省“浪潮杯”省赛 解题报告

    题目地址:http://acm.upc.edu.cn/problemset.php?page=13  2217~2226 A.Rescue The Princess 一个等边三角形告诉前2个点,求逆时 ...

  5. flask装饰器route实现路由功能理解

    利用装饰器的方式实现了路由函数,这是一个十分简单清晰的结构,而这个功能的实现,有着很大的学习意义 @appweb.route('index',methods=['GET','POST'] def st ...

  6. ModuleNotFoundError: No module named 'urlparse'

    这是2.x转3.x问题 2.x写法: from urlparse import urlparse   3.x写法: from urllib.parse import urlparse 问题解决.

  7. Python不兼容问题

    今天遇到了一个Python2与3不兼容的坑. ride是基于robot框架的python自动化ui,但它只支持python2,而我电脑环境只有python3,想跑别人基于ride编写的测试用例,折腾了 ...

  8. jquery plupload上传插件

    http://www.jianshu.com/p/047349275cd4 http://www.cnblogs.com/2050/p/3913184.html demo地址: http://chap ...

  9. 基于ASP.Net Core开发一套通用后台框架记录-(数据库设计(权限模块))

    写在前面 本系列博客是本人在学习的过程中搭建学习的记录,如果对你有所帮助那再好不过.如果您有发现错误,请告知我,我会第一时间修改. 前期我不会公开源码,我想是一点点敲代码,不然复制.粘贴那就没意思了. ...

  10. [COCI2006-2007 Contest#3] BICIKLI

    不难的一道题,就是码的时候出了点问题,看了其他巨佬的题解才发现问题所在... 题目大意: 给定一个有向图,n个点,m条边.请问,1号点到2号点有多少条路径?如果有无限多条,输出inf,如果有限,输出答 ...