垃圾收集器

垃圾收集器

引用计数器:

从gc日志可以看出是回收了,java虚假没有选用引用计数器算法管理内存

可达性分析算法

?线程池中线程是维持一个数量还是,用已经有的线程?

回收方法区

垃圾收集器

垃圾收集器根据应用场景和内存回收范围来选择。根据新生代、老年代,高性能服务器、客户端,计算密集场景、高响应场景。选择不同的收集器。

单线程收集器

单线程收集器,是使用单线程去完成垃圾回收工作。在垃圾收集的同时要暂停其它所有的工作线程,直到收集结束。即"Stop The World"。

多线程收集器

并行收集器:多条垃圾回收线程。工作线程处于等待状态。

并发收集器:多线程垃圾回收。工作线程继续运行。

HotSpot垃圾回收器

1、Serial(串行收集器):用于新生代GC,复制算法,启动时默认为Client模式,GC的线程为单线程。单线程性能很高。对于内存较小的新生代,停顿时间很短。

2、ParNew(并行收集器):与Serial类似,不同点在于它一般用于新生代的并行回收,而且通常情况下运行在Server模式。只有他能与CMS收集器配合工作。

3、Parallel Scavenge(并行回收):设计目标达到一个可控制的吞吐量。用于新生代回收,复制算法,并行收集。适用于后台预算不需要太多交互的任务。通过参数课控制吞吐量和停顿时间。自适应调节策略打开之后会根据虚拟机监控信息动态调整新生代。

4、Serial Old(串行收集器):是Serial收集器的老年代版本,使用标记-整理收集算法,主要用于启动模式为Client的JVM或者用于CMS收集器失败后的后备方案。

5、Parallel Old(并行收集器):是Parallel Scavenge的老年代版本,使用标记-整理收集算法。设计目标为吞吐量有限。搭配Parallel Scavenge,用于高吞吐量以及CPU敏感场合。目前JDK1.8作为默认的垃圾收集器。

6、Concurrent Mark Sweep,CMS(并发收集器):目标为希望系统停顿时间最短。使用标记-清除算法,根据参数定期清理内存碎片。会产生大量的内存碎片,根据配置定期做碎片整理。如果因碎片问题导致垃圾回收失败,选择Serial 收集器做Full GC。

  • CMS Failure Mode

  • 上文提到在正常的情况下CMS整个流程的暂停时间都是很短的,一般也就在10ms~100ms左右。然而这与线上的情况并不相符,线上集群在读写压力很大的情况下,经常会出现长时间的卡顿,有些卡顿甚至长达几分钟,导致很严重的读写阻塞,甚至会造成Region Server和Zookeeper之间Session超时,使得Region Server异常离线。实际上,CMS并不是很完美,它会在两种场景下产生严重的Full GC,接下来分别进行介绍。
  • Concurrent Failure

  • 这种场景其实比较简单,假如现在系统正在执行CMS回收老生代空间,在回收的过程中新生代来了一批对象进来,不巧的是,老生代已经没有空间再容纳这些对象了。这种场景下,CMS回收器会停止继续工作,系统进入 ‘stop-the-world‘ 模式,并且回收算法会退化为单线程复制算法,重新分配整个堆内存的存活对象到S0中,释放所有其他空间。很显然,整个过程会非常‘漫长‘。但是这种问题也很容易解决,只需要让CMS回收器更早一点回收就可以避免。JVM提供了参数-XX:CMSInitiatingOccupancyFraction=N来设置CMS回收的时机,其中N表示当前老生代已使用内存占新生代总内存的比例,该值默认为68,可以将该值修改的更小使得回收更早进行。
  • Promotion Failure

  • 假设此时设置XX:CMSInitiatingOccupancyFraction=60,但是在已使用内存还没有达到总内存60%的时候,已经没有空间容纳从新生代迁移的对象了。oh,my god!怎么会这样?罪魁祸首就是内存碎片,上文中提到CMS算法会产生大量碎片,当碎片容量积累到一定大小之后就会造成上面的场景。这种场景下,CMS回收器一样会停止工作,进入漫长的 ‘stop-the-world‘ 模式。JVM也提供了参数 -XX: UseCMSCompactAtFullCollection来减少碎片的产生,这个参数表示会在每次CMS回收垃圾之后执行一次碎片整理,很显然,这个参数会对性能有比较大的影响。

7、Garbage-First,G1(并发与并行)收集器:JDK1.7开始使用。目标为未来可以替换CMS收集器,使用标记-整理收集算法。可预测的停顿。并且可以同时用于新生代和老年代。思想:把内存分块,优先回收价值最大的块。关于G1收集器性能的测试。结果是略逊于CMS。

理解GC日志

2017-02-21T14:52:06.941+0800: 343679.497:

//GC 表示年轻代垃圾回收 java虚拟机启动以来经过的秒数

[GC2017-02-21T14:52:06.941+0800: 343679.497:

//使用ParNew作为年轻代的垃圾回收:年轻代垃圾回收前的大小->回收后大小//(总大小),回收时间

[ParNew: 164680K->600K(184320K), 0.0022530 secs]

//堆垃圾回收前的大小->堆回收后大小(总大小),回收时间

426032K->261971K(1028096K), 0.0024010 secs]

//用户态、内核态消耗的cpu时间和实际耗时。

[Times: user=0.04 sys=0.00, real=0.00 secs]

Serial收集器中的新生代名为"Default NewGeneration",所以显示的是"[DefNew"。如果是ParNew收集器,新生代名称就会变为"[ParNew",意为"Parallel New Generation"。如果采用Parallel Scavenge收集器,那它配套的新生代称为"PSYoungGen",老年代和永久代同理,名称也是由收集器决定的。

垃圾回收时机

回收点

安全区

时间: 2024-10-27 04:24:14

垃圾收集器的相关文章

垃圾收集器与内存分配策略

①对于java虚拟机来说,垃圾收集器主要关注的内存区域是 堆和方法区. ②垃圾收集器就是要收集那些已经“死了”的对象.如果判断一个对象是否存活? 对象引用计数法 对象引用增加一个,那么相应的计数器加1,否则,减1. 优点:实现简单 缺点:不能处理对象间的循环引用.a引用b,b同时引用a. 可达性分析 如果节点到root节点可达,则证明是存活的:否则,已死.所以对于下图的o5,o6,o7虽然他们是循环引用的,但是到root节点无可达,所以已死可清除. ③垃圾回收器对于不同类型引用的回收规则 强引用

看图说说JVM老年代垃圾收集器

注:G1垃圾收集器是目前最前沿的GC收集器,未来将取代CMS垃圾收集器,可以作为整个Heap的收集器使用,不限于老年代!!!

JVM垃圾回收机制总结(5) :JDK垃圾收集器的配置命令

以下配置主要针对分代垃圾回收算法而言. 堆大小设置 年轻代的设置很关键 JVM中最大堆大小有三方面限制:相关操作系统的数据模型(32-bt还是64-bit)限制:系统的可用虚拟内存限制:系统的可用物理内存限制.32位系统下,一般限制在1.5G~2G:64为操作系统对内存无限制.在Windows Server 2003 系统,3.5G物理内存,JDK5.0下测试,最大可设置为1478m. 典型设置: java -Xmx3550m -Xms3550m -Xmn2g –Xss128k -Xmx3550

Java虚拟机垃圾收集器

垃圾收集器用到的垃圾收集算法 标记-清除(Mark-Sweep)算法: 首先标记出所有需要回收的对象,在标记完成后统一回收所有被标记的对象.它主要有两个缺点:一个是效率问题,标记和清楚过程的效率都不高:另外一个是空间问题,标记清楚后会产生大量不连续的内存碎片,空间碎片太多可能会导致,当程序在以后的运行过程中需要分配较大对象时无法找到足够连续的内存空间而不得不提前出发另一次垃圾收集动作. 执行过程如下图所示: 复制算法: 它将可用内存按容量划分为大小相等的两块,每次只是用其中一块.当这一块的内存用

垃圾收集器与内存分配策略(一)

1.判断对象是否存活 a.计数器算法  算法描述:给对象中添加一个引用计数器,每当有一个地方引用它时,计数器值加1:当引用失效时,计数器值减1:任何时刻计数器为0的对象就是不可能再被使用的. 该算法实现简单,效率也很高,但是Java虚拟机中没有使用计数器算法来管理内存,主要原因就是它很难解决对象之间相互循环引用的问题.  b.可达性分析算法 算法描述:通过一系列的称为"GC Roots"的对象作为起点,从这些节点开始向下进行搜索,搜索所走过的路径称为引用链,当一个对象到GC Roots

GC算法 垃圾收集器

GC算法 垃圾收集器 参考:http://www.cnblogs.com/ityouknow/p/5614961.html 概述 垃圾收集 Garbage Collection 通常被称为“GC”,它诞生于1960年 MIT 的 Lisp 语言,经过半个多世纪,目前已经十分成熟了. jvm 中,程序计数器.虚拟机栈.本地方法栈都是随线程而生随线程而灭,栈帧随着方法的进入和退出做入栈和出栈操作,实现了自动的内存清理,因此,我们的内存垃圾回收主要集中于 java 堆和方法区中,在程序运行期间,这部分

深入理解JVM之四:详解垃圾收集器

前言 前面已经对垃圾收集算法有了较为详细的介绍,这里我们将对JVM中具体的垃圾回收器进行介绍,在虚拟机规范中并没有对垃圾回收器如何实现具体介绍,因此每个厂商的垃圾回收器可能会完全不同,但是我们介绍的是基于JDK1.7之后的Hotspot虚拟机(包括前面对Java虚拟机的介绍也是基于jdk1.7版本的).在Hotspot中,虚拟机的收集器主要有下: 可以看到垃圾收集器是按对象的分代来划分的,可以用线条连接的垃圾回收器表示两者可以配合使用.可以看到新生代垃圾收集器有Serial.ParNew.Par

深入理解JVM:垃圾收集器与内存分配策略

堆里面存放着Java世界几乎所有的对象实例,垃圾收集器在对堆进行回收前,第一件事情就是要确定这些对象之中哪些还存活,哪些已经死去.判断对象的生命周期是否结束有以下几种方法 引用计数法 具体操作是给对象添加一个引用计数器,每当有一个地方引用时,计数器的值就加1,:当引用失效时,计数器就减1:任何时刻计数器为0的对象就 是不可能再被使用的.客观的说引用计数器算法实现简单,判定效率也很高,在大部分情况下他都是一个不错的算法.但是引用计数器有缺陷 举个简单的例子,对象A和对象B都有字段instance,

【转】Java垃圾收集器

原文链接 http://www.cnblogs.com/gw811/archive/2012/10/19/2730258.html#top Java垃圾收集器 概述 说起垃圾收集(Garbage Collection,GC),大部分人都把这项技术当做Java语言的伴生产物.事实上,GC的历史远远比Java久远,1960年诞生于MIT的Lisp是第一门真正使用内存动态分配和垃圾收集技术的语言.当Lisp还在胚胎时期时,人们就在思考: GC需要完成的三件事情: 哪些内存需要回收? 什么时候回收? 如