Reference:https://time.geekbang.org/column/article/107396
GC算法
JVM提供了不同的回收算法来实现这⼀套回收机制,通常垃圾收集器的回收算法可以分为以下⼏种:
如果说收集算法是内存回收的⽅法论,那么垃圾收集器就是内存回收的具体实现,JDK1.7 update14 之后Hotspot虚拟机所有的回收器整理如下(以下为服务端垃圾收集器):
其实在JVM规范中并没有明确GC的运作⽅式,各个⼚商可以采⽤不同的⽅式实现垃圾收集器。我们可以通过JVM⼯具查询当前JVM使⽤的垃圾收集器类型,⾸先通过ps命令查询出经常ID,再通过jmap -heap ID查询出JVM的配置信息,其中就包括垃圾收集器的设置类型。
GC性能衡量指标
⼀个垃圾收集器在不同场景下表现出的性能也不⼀样,那么如何评价⼀个垃圾收集器的性能好坏呢?我们可以借助⼀些指标。
吞吐量:这⾥的吞吐量是指应⽤程序所花费的时间和系统总运⾏时间的⽐值。我们可以按照这个公式来计算GC的吞吐量:系统总运⾏时间=应⽤程序耗时+GC耗时。如果系统运⾏了100分钟,GC耗时1分钟,则系统吞吐量为99%。GC的吞吐量⼀般不能低于95%。
停顿时间:指垃圾收集器正在运⾏时,应⽤程序的暂停时间。对于串⾏回收器⽽⾔,停顿时间可能会⽐较长;⽽使⽤并发回收器,由于垃圾收集器和应⽤程序交替运⾏,程序的停顿时间就会变短,但其效率很可能不如独占垃圾收集器,系统的吞吐量也很可能会降低。
垃圾回收频率:多久发⽣⼀次指垃圾回收呢?通常垃圾回收的频率越低越好,增⼤堆内存空间可以有效降低垃圾回收发⽣的频率,但同时也意味着堆积的回收对象越多,最终也会增加回收时的停顿时间。所以我们只要适当地增⼤堆内存空间,保证正常的垃圾回收频率即可。
GC调优策略
找出问题后,就可以进⾏调优了,下⾯介绍⼏种常⽤的GC调优策略。
1. 降低Minor GC频率
通常情况下,由于新⽣代空间较⼩,Eden区很快被填满,就会导致频繁Minor GC,因此我们可以通过增⼤新⽣代空间来降低Minor GC的频率。
可能你会有这样的疑问,扩容Eden区虽然可以减少Minor GC的次数,但不会增加单次Minor GC的时间吗?如果单次Minor GC的时间增加,那也
很难达到我们期待的优化效果呀。
我们知道,单次Minor GC时间是由两部分组成:T1(扫描新⽣代)和T2(复制存活对象)。假设⼀个对象在Eden区的存活时间为500ms,
Minor GC的时间间隔是300ms,那么正常情况下,Minor GC的时间为 :T1+T2。
当我们增⼤新⽣代空间,Minor GC的时间间隔可能会扩⼤到600ms,此时⼀个存活500ms的对象就会在Eden区中被回收掉,此时就不存在复制
存活对象了,所以再发⽣Minor GC的时间为:两次扫描新⽣代,即2T1。
可见,扩容后,Minor GC时增加了T1,但省去了T2的时间。通常在虚拟机中,复制对象的成本要远⾼于扫描成本。
如果在堆内存中存在较多的长期存活的对象,此时增加年轻代空间,反⽽会增加Minor GC的时间。如果堆中的短期对象很多,那么扩容新⽣
代,单次Minor GC时间不会显著增加。因此,单次Minor GC时间更多取决于GC后存活对象的数量,⽽⾮Eden区的⼤⼩。
2. 降低Full GC的频率
通常情况下,由于堆内存空间不⾜或⽼年代对象太多,会触发Full GC,频繁的Full GC会带来上下⽂切换,增加系统的性能开销。我们可以使
⽤哪些⽅法来降低Full GC的频率呢?
减少创建⼤对象:在平常的业务场景中,我们习惯⼀次性从数据库中查询出⼀个⼤对象⽤于web端显⽰。例如,我之前碰到过⼀个⼀次性查询
出60个字段的业务操作,这种⼤对象如果超过年轻代最⼤对象阈值,会被直接创建在⽼年代;即使被创建在了年轻代,由于年轻代的内存空间
有限,通过Minor GC之后也会进⼊到⽼年代。这种⼤对象很容易产⽣较多的Full GC。
我们可以将这种⼤对象拆解出来,⾸次只查询⼀些⽐较重要的字段,如果还需要其它字段辅助查看,再通过第⼆次查询显⽰剩余的字段。
增⼤堆内存空间:在堆内存不⾜的情况下,增⼤堆内存空间,且设置初始化堆内存为最⼤堆内存,也可以降低Full GC的频率。
选择合适的GC回收器
假设我们有这样⼀个需求,要求每次操作的响应时间必须在500ms以内。这个时候我们⼀般会选择响应速度较快的GC回收器,CMS(Concurrent Mark Sweep)回收器和G1回收器都是不错的选择。
⽽当我们的需求对系统吞吐量有要求时,就可以选择Parallel Scavenge回收器来提⾼系统的吞吐量。
总结
垃圾收集器的种类很多,我们可以将其分成两种类型,⼀种是响应速度快,⼀种是吞吐量⾼。
通常情况下,CMS和G1回收器的响应速度快,Parallel Scavenge回收器的吞吐量⾼。
在JDK1.8环境下,默认使⽤的是Parallel Scavenge(年轻代)+ Serial Old(⽼年代)垃圾收集器,你可以通过⽂中介绍的查询JVM的GC默认配置⽅法进⾏查看。
通常情况,JVM是默认垃圾回收优化的,在没有性能衡量标准的前提下,尽量避免修改GC的⼀些性能配置参数。如果⼀定要改,那就必须基于⼤量的测试结果或线上的具体性能来进⾏调整。
相关推荐
JVM与GC调优课程视频 〖课程介绍〗: JVM与GC调优课程视频 〖课程目录〗: 1.笔记/ ├── 第1篇-字节码篇.png?x-oss-process=style/pnp8 ├── 第2篇-类的加载篇.png?x-oss-process=style/pnp8 ├── 第3篇-运行时...
### JVM_GC调优详解 #### 一、JVM体系结构概览 Java虚拟机(JVM)作为Java程序的运行环境,其内部结构复杂且高效。为了更好地理解JVM_GC调优,我们首先来了解一下JVM的基本组成部分。 1. **类装载器子系统(Class ...
大厂架构师-日均百万订单量的JVM优化与高级GC调优策略实战(5.8G) 〖课程介绍〗: 来自顶尖大厂的架构师级JVM优化与GC调优策略实战课程,是具备有尖端技术的优化课程。在课程内容上几乎不用过多的介绍,单是查阅目录就...
**JVM体系结构与GC调优** Java虚拟机(JVM)是Java应用程序的核心组成部分,它为Java程序提供了一个运行时环境。理解JVM的体系结构对于优化Java应用的性能至关重要,尤其是垃圾收集(Garbage Collection, GC)的...
jvm体系结构与GC调优,图文齐飞,方便理解,,非常适合入门的java工程师以及性能测试工程师阅读,欢迎大家下载
GC调优是优化Java应用程序性能的关键环节,尤其是在大型系统中,正确配置和调整GC参数可以显著减少程序暂停时间,提高整体运行效率。 在Java中,堆内存是GC的主要工作区域,它分为新生代、老年代和永久代(Java 8...
在Java应用程序中,尤其是对于大型系统或高并发环境,进行JVM GC调优是提升性能、减少系统停顿时间的关键步骤。"用于测试jvm gc调优-share-jvm-gc.zip"这个压缩包文件很可能包含了一些工具、脚本或教程,用于帮助...
JVM体系结构与GC调优
GC调优主要是对JVM的垃圾回收机制进行调整,以确保内存的有效利用和避免系统出现长时间的暂停。垃圾回收是JVM自动管理内存的过程,其目标是回收不再使用的对象所占用的内存空间。主要涉及以下几个方面: 1. **垃圾...
本资料"jvm-full-gc调优-jvm-full-gc.zip"显然是针对如何减少和优化JVM的Full GC进行深入探讨的。以下将详细介绍JVM Full GC的相关知识点。 1. **理解JVM内存结构**:Java内存主要分为堆内存(Heap)和非堆内存...
JVM体系结构与GC调优,46页+PPT,包括JVM体系结构概述、GC算法介绍、内存管理、垃圾回收、调优方法和监控工具
JVM体系结构与GC调优