文档章节

JVM调优总结(4):分代垃圾回收

A
 Alson清
发布于 2016/09/29 15:10
字数 2460
阅读 2
收藏 0

来源:pengjiaheng

网址:http://pengjiaheng.iteye.com/blog/524024

 

为什么要分代

 

分代的垃圾回收策略,是基于这样一个事实:不同的对象的生命周期是不一样的。因此,不同生命周期的对象可以采取不同的收集方式,以便提高回收效率。

 

在Java程序运行的过程中,会产生大量的对象,其中有些对象是与业务信息相关,比如Http请求中的Session对象、线程、Socket连接,这类对象跟业务直接挂钩,因此生命周期比较长。但是还有一些对象,主要是程序运行过程中生成的临时变量,这些对象生命周期会比较短,比如:String对象,由于其不变类的特性,系统会产生大量的这些对象,有些对象甚至只用一次即可回收。

 

试想,在不进行对象存活时间区分的情况下,每次垃圾回收都是对整个堆空间进行回收,花费时间相对会长,同时,因为每次回收都需要遍历所有存活对象,但实际上,对于生命周期长的对象而言,这种遍历是没有效果的,因为可能进行了很多次遍历,但是他们依旧存在。因此,分代垃圾回收采用分治的思想,进行代的划分,把不同生命周期的对象放在不同代上,不同代上采用最适合它的垃圾回收方式进行回收。

 

如何分代

 

 

如图所示:

 

虚拟机中的共划分为三个代:年轻代(Young Generation)、年老点(Old Generation)和持久代(Permanent Generation)。其中持久代主要存放的是Java类的类信息,与垃圾收集要收集的Java对象关系不大。年轻代和年老代的划分是对垃圾收集影响比较大的。

 

年轻代:

 

所有新生成的对象首先都是放在年轻代的。年轻代的目标就是尽可能快速的收集掉那些生命周期短的对象。年轻代分三个区。一个Eden区,两个Survivor区(一般而言)。大部分对象在Eden区中生成。当Eden区满时,还存活的对象将被复制到Survivor区(两个中的一个),当这个Survivor区满时,此区的存活对象将被复制到另外一个Survivor区,当这个Survivor去也满了的时候,从第一个Survivor区复制过来的并且此时还存活的对象,将被复制“年老区(Tenured)”。需要注意,Survivor的两个区是对称的,没先后关系,所以同一个区中可能同时存在从Eden复制过来 对象,和从前一个Survivor复制过来的对象,而复制到年老区的只有从第一个Survivor去过来的对象。而且,Survivor区总有一个是空的。同时,根据程序需要,Survivor区是可以配置为多个的(多于两个),这样可以增加对象在年轻代中的存在时间,减少被放到年老代的可能。

 

年老代:

 

在年轻代中经历了N次垃圾回收后仍然存活的对象,就会被放到年老代中。因此,可以认为年老代中存放的都是一些生命周期较长的对象。

 

持久代:

 

用于存放静态文件,如今Java类、方法等。持久代对垃圾回收没有显著影响,但是有些应用可能动态生成或者调用一些class,例如Hibernate等,在这种时候需要设置一个比较大的持久代空间来存放这些运行过程中新增的类。持久代大小通过-XX:MaxPermSize=<N>进行设置。

 

什么情况下触发垃圾回收

 

由于对象进行了分代处理,因此垃圾回收区域、时间也不一样。GC有两种类型:Scavenge GC和Full GC。

 

Scavenge GC

 

一般情况下,当新对象生成,并且在Eden申请空间失败时,就会触发Scavenge GC,对Eden区域进行GC,清除非存活对象,并且把尚且存活的对象移动到Survivor区。然后整理Survivor的两个区。这种方式的GC是对年轻代的Eden区进行,不会影响到年老代。因为大部分对象都是从Eden区开始的,同时Eden区不会分配的很大,所以Eden区的GC会频繁进行。因而,一般在这里需要使用速度快、效率高的算法,使Eden去能尽快空闲出来。

 

Full GC

 

对整个堆进行整理,包括Young、Tenured和Perm。Full GC因为需要对整个对进行回收,所以比Scavenge GC要慢,因此应该尽可能减少Full GC的次数。在对JVM调优的过程中,很大一部分工作就是对于FullGC的调节。有如下原因可能导致Full GC:

 

· 年老代(Tenured)被写满

 

· 持久代(Perm)被写满

 

· System.gc()被显示调用

 

·上一次GC之后Heap的各域分配策略动态变化

 

分代垃圾回收流程示意

 

 

 

 

选择合适的垃圾收集算法

 

串行收集器

 

 

用单线程处理所有垃圾回收工作,因为无需多线程交互,所以效率比较高。但是,也无法使用多处理器的优势,所以此收集器适合单处理器机器。当然,此收集器也可以用在小数据量(100M左右)情况下的多处理器机器上。可以使用-XX:+UseSerialGC打开。

 

并行收集器

 

 

对年轻代进行并行垃圾回收,因此可以减少垃圾回收时间。一般在多线程多处理器机器上使用。使用-XX:+UseParallelGC.打开。并行收集器在J2SE5.0第六6更新上引入,在Java SE6.0中进行了增强–可以对年老代进行并行收集。如果年老代不使用并发收集的话,默认是使用单线程进行垃圾回收,因此会制约扩展能力。使用-XX:+UseParallelOldGC打开。

 

使用-XX:ParallelGCThreads=<N>设置并行垃圾回收的线程数。此值可以设置与机器处理器数量相等。

 

此收集器可以进行如下配置:

 

最大垃圾回收暂停:指定垃圾回收时的最长暂停时间,通过-XX:MaxGCPauseMillis=<N>指定。<N>为毫秒.如果指定了此值的话,堆大小和垃圾回收相关参数会进行调整以达到指定值。设定此值可能会减少应用的吞吐量。

 

吞吐量:吞吐量为垃圾回收时间与非垃圾回收时间的比值,通过-XX:GCTimeRatio=<N>来设定,公式为1/(1+N)。例如,-XX:GCTimeRatio=19时,表示5%的时间用于垃圾回收。默认情况为99,即1%的时间用于垃圾回收。 

 

并发收集器

 

可以保证大部分工作都并发进行(应用不停止),垃圾回收只暂停很少的时间,此收集器适合对响应时间要求比较高的中、大规模应用。使用-XX:+UseConcMarkSweepGC打开。

 

 

并发收集器主要减少年老代的暂停时间,他在应用不停止的情况下使用独立的垃圾回收线程,跟踪可达对象。在每个年老代垃圾回收周期中,在收集初期并发收集器 会对整个应用进行简短的暂停,在收集中还会再暂停一次。第二次暂停会比第一次稍长,在此过程中多个线程同时进行垃圾回收工作。

 

并发收集器使用处理器换来短暂的停顿时间。在一个N个处理器的系统上,并发收集部分使用K/N个可用处理器进行回收,一般情况下1<=K<=N/4。

 

在只有一个处理器的主机上使用并发收集器,设置为incremental mode模式也可获得较短的停顿时间。

 

浮动垃圾:由于在应用运行的同时进行垃圾回收,所以有些垃圾可能在垃圾回收进行完成时产生,这样就造成了“Floating Garbage”,这些垃圾需要在下次垃圾回收周期时才能回收掉。所以,并发收集器一般需要20%的预留空间用于这些浮动垃圾。

 

Concurrent Mode Failure:并发收集器在应用运行时进行收集,所以需要保证堆在垃圾回收的这段时间有足够的空间供程序使用,否则,垃圾回收还未完成,堆空间先满了。这种情况下将会发生“并发模式失败”,此时整个应用将会暂停,进行垃圾回收。

 

启动并发收集器:因为并发收集在应用运行时进行收集,所以必须保证收集完成之前有足够的内存空间供程序使用,否则会出现“Concurrent Mode Failure”。通过设置-XX:CMSInitiatingOccupancyFraction=<N>指定还有多少剩余堆时开始执行并发收集

 

小结

 

串行处理器:

 

–适用情况:数据量比较小(100M左右);单处理器下并且对响应时间无要求的应用。

–缺点:只能用于小型应用

 

并行处理器:

 

–适用情况:“对吞吐量有高要求”,多CPU、对应用响应时间无要求的中、大型应用。举例:后台处理、科学计算。

–缺点:垃圾收集过程中应用响应时间可能加长

 

并发处理器:

 

–适用情况:“对响应时间有高要求”,多CPU、对应用响应时间有较高要求的中、大型应用。举例:Web服务器/应用服务器、电信交换、集成开发环境。

本文转载自:http://mp.weixin.qq.com/s?__biz=MjM5NzMyMjAwMA==&mid=2651477060&idx=1&sn=bff7ff3ed88bab49a3015937d8c

A
粉丝 1
博文 13
码字总数 0
作品 0
浦东
私信 提问
JVM调优总结(5):典型配置

JVM调优总结(5):典型配置 2016-04-20(点击上方公众号,可快速关注) 来源:pengjiaheng网址:http://pengjiaheng.iteye.com/blog/538582 以下配置主要针对分代垃圾回收算法而言。 堆大小...

舒文joven
2018/07/17
0
0
JVM性能优化, Part 3 垃圾回收

ImportNew注:本文是JVM性能优化 系列-第3篇-《JVM性能优化, Part 3 —— 垃圾回收》 第一篇 《JVM性能优化, Part 1 ―― JVM简介 》 第二篇《JVM性能优化, Part 2 ―― 编译器》 Java平台...

梁杰_Jack
2014/10/30
0
0
JVM参数调优:Eclipse启动实践

JVM参数调优:Eclipse启动实践 本文主要参考自《深入理解 Java 虚拟机》。 这本书是国人写的难得的不是照搬代码注释的且不是废话连篇的技术书,内容涵盖了 Java 从源码到字节码到执行的整个过...

天天顺利
2015/01/13
0
0
Java编程——jvm优化之 图解垃圾回收

从这篇开始我们探讨一些jvm调优的问题。在jvm调优中一个离不开的重点是垃圾回收,当垃圾回收成为系统达到更高并发量的瓶颈时,我们就需要对jvm中如果进行“自动化”垃圾回收技术实施必要的监...

远方的梦Java
2018/08/06
0
0
JVM系列篇:JVM性能调优的6大步骤,及关键调优参数详解

本系列会持续更新。 一、JVM内存调优 对JVM内存的系统级的调优主要的目的是减少GC的频率和Full GC的次数。 1.Full GC 会对整个堆进行整理,包括Young、Tenured和Perm。Full GC因为需要对整个...

mikechen优知
03/26
0
0

没有更多内容

加载失败,请刷新页面

加载更多

rsync工具常用选项以及同步的两种方式

rsync -av /etc/passwd /tmp/1.txt #rsync的本机传输写法 rsync -av /tmp/1.txt 192.168.188.128:/tmp/2.txt #rsync的远程传输rsync格式rsync [OPTION] … SRC ......

林怡丰
今天
3
0
GatewayWorker 报错:stream_socket_server(): unable to connect to tcp://0.0.0.0:1238

GatewayWorker 报错:stream_socket_server(): unable to connect to tcp://0.0.0.0:1238 (Address already in use) 官方文档虽然有相同的问题,但是对我的问题没起作用…… 后面发现自己手贱...

wenzhizhong
昨天
3
0
REST接口

文章来源 https://zhuanlan.zhihu.com/p/28674721?group_id=886181549958119424 http://www.ruanyifeng.com/blog/2014/05/restful_api.html REST 对请求的约定 REST 用来规范应用如何在 HTTP......

Airship
昨天
5
0
Spring Cloud Config 统一配置中心

Spring Cloud Config 统一配置中心 一、统一配置中心 统一管理配置 通常,我们会使用配置文件来管理应用的配置。如一个 Spring Boot 的应用,可以将配置信息放在 application.yml 文件中,如...

非摩尔根
昨天
6
0
android ------ AAPT2 error: check logs for details解决方法

AAPT 是全称是 Android Asset Packaging Tool,它是构建 App,甚至是构建 Android 系统都必不可少的一个工具。它的作用是将所有资源文件压缩打包到Android APK 当中。我们在 Android SDK 目录...

切切歆语
昨天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部