GC学习入门 看这一篇就够了(基于Oracle JDK 8)
mhr18 2024-09-26 14:25 25 浏览 0 评论
1 JVM中Java对象的分类
JVM根据运行于其中的对象的生存时间, 将它们分为3种, 并分别存放在JVM的不同内存区域中. 这种对象存放空间的管理方式叫做 Generation管理方式.
如果想学习Java工程化、高性能及分布式、深入浅出。微服务、Spring,MyBatis,Netty源码分析的朋友可以加我的Java高级交流:854630135,群里有阿里大牛直播讲解技术,以及Java大型互联网技术的视频免费分享给大家。
- Young Generation (新生代, 又称年轻代): 用于存放"早逝"对象(即瞬时对象), 一般的 Java 应用中, 80%的对象都是"朝生息灭"的, 比如在创建对象或调用方法时使用的临时对象或局部变量.
- Tenured Generation (老年代): 用于存放"驻留"对象(即被引用较长时间的对象). 往往体现为一个大型程序中的全局对象或长时间被使用的对象.
- Perm Generation (永久代): 用于存放"永久"对象. 这些对象管理着运行于 JVM 中的类和方法.
2 JVM的GC类型及触发条件
2.1 Young GC
又叫 Minor GC(次收集), Young GC 经常发生, 且其每次消耗的时间较短 —— 它只对Young Generation中的对象进行垃圾收集.
- 触发条件:
- 在 Young Generation(新生代)的 Edne 区的空间不足以容纳新生成的对象时执行, 同时会将 Eden 区与 From Survivor 区中尚且存活的对象移动至空闲的 To Survivor 区中.
- —— 程序运行过程中, 始终有一个 Survivor 区是完全处于空闲状态的, 如果不是, 说明应用程序出现故障了.
2.2 Full GC
又叫 Major GC(主收集), 是对整个 Java Heap 中的对象(不包括永久代/元空间)进行垃圾收集, 此 GC 操作耗时久, 对系统的性能影响较大, 因此在 JVM 的调优中, 很多工作是针对 Full GC 的调优 —— 要尽可能减少 Full GC 的频率.
Full GC 是一种"昂贵"的垃圾收集方式, 它要对整个Heap 进行垃圾收集, 并做一定的空间整理, 这会使 Stop-The-World 的时间变长.
- Full GC的触发条件:
1) 年老代(Tenured)空间不足:
- 通过 Minor GC 后进入老年代的对象的体积大于老年代的可用空间;
- 由Eden块、From Space 块向 To Space 复制存活对象时, 它们的体积大于 To Space 的大小, 系统就会把这些对象转存到老年代, 而老年代的可用空间小于这些对象的体积.
2) System.gc() 被显式调用, 系统建议执行 Full GC, 但并不会立即执行 —— 非常影响程序性能, 建议禁止使用;
3) 上一次 GC 之后 Heap 各个区域空间的动态变化.
3 Java对象生成时的内存申请过程
1) JVM 会试图为相关 Java 对象在年轻代的 Eden 区中初始化一块内存区域;
2) 当 Eden 区空间足够时, 内存申请结束. 否则执行下一步;
3) JVM 试图释放在 Eden 区中所有不活跃的对象(即 出发Young GC), 释放后若Eden空间仍然不足以放入新对象时, JVM 会试图将部分 Eden 区中活跃的对象迁移至 Survivor 区;
4) Survivor 区被用来作为 Eden 区及老年代的中间交换区域, 当老年代空间足够时, Survivor 区中存活了一定次数的对象会被迁移到老年代;
如果想学习Java工程化、高性能及分布式、深入浅出。微服务、Spring,MyBatis,Netty源码分析的朋友可以加我的Java高级交流:854630135,群里有阿里大牛直播讲解技术,以及Java大型互联网技术的视频免费分享给大家。
5) 当年老代空间不够时, JVM会在老年代进行完全的垃圾回收(Full GC);
6) Full GC 后, 若 Survivor 区及老年代仍然无法存放从 Eden 区复制过来的对象, 则会导致 JVM 无法在 Eden 区为新生成的对象申请内存, 即出现 "Out of Memory".
- OOM(Out of Memory)异常一般主要有如下2种原因:
- 1) 老年代溢出, 表现为: java.lang.OutOfMemoryError:Javaheapspace
- 这是最常见的情况, 产生的原因可能是: 设置的内存参数-Xmx过小或程序的内存泄露及使用不当问题.
- 2) 持久代溢出,表现为: java.lang.OutOfMemoryError:PermGenspace
- 通常由于持久代设置过小, 动态加载了大量 Java 类而导致溢出, 解决办法唯有将参数 -XX:MaxPermSize 调大(一般256m能满足绝大多数应用程序需求).
3 Oracle JDK中的垃圾收集器
3.1 串行收集器(Serial Collector)
只有一条GC线程, 运行时需要暂停用户程序(Stop-The-World).
实现: Serial(用于新生代, 采用复制算法)、serial old(用于老年代, 采用标记-整理算法).
3.2 并行收集器(Parallel Collector)
有多条GC线程, 运行时也需要暂停用户程序(Stop-The-World).
实现: ParNew(用于新生代, 采用复制算法)、Parallel Scavenge(用于新生代, 采用复制算法)、Parallel Old(用于老年代, 采用标记-整理算法).
3.3 并发收集器(Concurrent Collector)
有一条或多条GC线程, 且需要在部分阶段暂停用户程序(Stop-The-World), 部分阶段与用户程序并发执行.
实现: Concurrent Mark Sweep(CMS, 用于老年代, 采用标记-清除算法).
- 并发(concurrent)与并行(parallel)的比较:
- 并发就是两个任务(A和B)需要独立运行, 在任务A结束之前, 任务B开始执行 --- 即表面上多个任务同时执行.
- 并行, 类比串行, 是微观概念, 即在每一个时刻都有多个任务在同时执行, 形象点理解为多管齐下, 串行可理解为单列队列, 同一时刻只能执行一个任务.
- 事实上, 并行是并发的一种实现方式, 还有一种并发的实现方式, 即我们熟悉的时间片切换 --- 任务A执行一段时间, CPU再切换到任务B执行一段时间, 如此交替执行. 时间片切换在微观上仍然是串行 --- 某一具体时刻只有一个任务在执行, 而在宏观上, 即一段时间内, 有多个任务得到了执行.
- 总结: 并行必须在多核多处理器或分布式系统(本质还是多核多处理器)中才能发生, 而单核处理器上只能发生时间片切换.
3.4 G1收集器(Garbage First GC)
G1垃圾回收器在 Oracle JDK 7 开始提供完整支持, 它是 server 型的 GC, 主要针对多核处理器和大内存的服务器, 能够以很高的概率 满足开发人员对停顿时间的要求, 同时还能保证高吞吐量.
- 与 CMS 收集器相比, G1收集器的优势:
- 1) 基于标记-整理算法, 不会产生大量的内存碎片;
- 2) 可以更加精确地控制停顿时间, 在不牺牲吞吐量前提下, 实现低停顿垃圾回收.
- G1收集器的实现原理:
- G1收集器能够避免全区域的垃圾收集, 它把堆内存划分为大小固定的几个独立区域, 并跟踪这些区域的垃圾收集进度, 同时在后台维护一个优先级列表, 每次根据所允许的收集时间, 优先回收垃圾最多的区域.
- —— 区域划分和优先级区域回收机制, 确保G1收集器可以在有限的时间内获得最高的垃圾收集效率.
- G1的长期目标是取代CMS (Concurrent Mark-Sweep Collector) 并发标记-清除收集器.
3.5 其他概念说明
- 为了更大程度地榨取机器性能, 新生代的收集器都使用了复制算法, 老年代的收集器都使用 标记-清除 或 标记-整理 算法. 关于各算法详情, 请参阅: JVM内存管理———垃圾搜集器参数精解.
- 在实际应用中, 需要对JVM的新生代、老年代分别选择合适的垃圾收集器.
- 这里新生代和老年代都分别有三种实现, 但由于收集器的实现方式不同, 部分组合无法一起配合工作, 经过验证, 这六种垃圾收集器只有六种可用组合.
4 GC的配置参数
4.1 参数名称的说明
4.1.1 标准参数(-)
所有 JVM 都必须支持这些参数的功能, 而且向后兼容, 如:
- -client : 设置 JVM 使用 client 模式, 特点是启动速度比较快, 但运行时性能和内存管理效率不高. 通常用于客户端应用程序或开发调试; 在32位环境下直接运行 Java 程序默认启用该模式.
- -server : 设置 JVM 使 server 模式, 特点是启动速度比较慢, 但运行时性能和内存管理效率很高, 适用于生产环境; 在具有64位能力的JDK环境下默认启用该模式.
4.1.2 非标准参数(-X)
各 JVM 厂商应该全部实现这些参数的功能, 但并不能保证这些厂商提供的 JVM 中都实现了这些功能, 且不保证向后兼容;
4.1.3 非稳定参数(-XX)
如果想学习Java工程化、高性能及分布式、深入浅出。微服务、Spring,MyBatis,Netty源码分析的朋友可以加我的Java高级交流:854630135,群里有阿里大牛直播讲解技术,以及Java大型互联网技术的视频免费分享给大家。
此类参数在各个 JVM 的实现中会有所不同, 将来也可能不被支持, 要慎重使用.
- 注意: 在"-XX:"后的参数若不需要赋值, 即只是用来配置开启或关闭相应选项, 则需要有 "+" (开启) 或 "-" (禁止) , 否则应用程序将在日志文件 (如 Tomcat 的日志文件 catalina.out ) 中抛出如下错误:
Missing +/- setting for VM option 'UseConcMarkSweepGC'. Error: Could not create the Java Virtual Machine. Error: A fatal exception has occurred. Program will exit.
- 可以看出, 这里缺少了 "+/-" 符号, 导致虚拟机启动异常, 修改后即可正常启动.
4.2 串行GC参数
-XX:+UseSerialGC # 使用 Serial & Serial Old 串行收集器(JDK 5以前的主要收集方式), 是client模式的默认设置.
4.3 并行GC参数(吞吐量优先)
-XX:+UseParNewGC # 使用 ParNew & Serial Old 收集器, 即对新生代使用并行收集, 提高收集效率(缩短Young GC的时间), 不推荐. -XX:+UseParallelGC # 使用 Parallel Scavenge & Parallel Old 并行收集器, 吞吐量优先, 会消耗更多内存, 是server模式的默认设置. -XX:+UseParallelOldGC # 对老年代使用 Parallel Old 并行收集器(JDK 6开始支持). -XX:ParallelGCThreads=20 # 配置并行收集器的线程数, 即并行执行垃圾收集任务的线程个数. # 此值最好与CPU处理器的个数相同(默认即相同). -XX:GCTimeRatio=49 # 设置系统用作GC的时间比例, 如49, 则GC时间比为 1/(1+49) = 2%, 即Java用2%的时间来做垃圾收集. # 如果此值设置过大, 即GC时间太少导致GC无法完成, JVM会压缩新生代的大小以适应此配置. -XX:MaxGCPauseMillis=100 # 设置每次新生代垃圾收集的最长毫秒值, 如果时间久而新生代的大小不足以支撑到此时间, # JVM会自动调整新生代的大小以满足此值. 若仍然无法满足, 则会调整GCTimeRatio. -XX:+UseAdaptiveSizePolicy # 使并行收集器自动设定 Eden 区的大小与相应的 Survivor 区的比例, # 以达到目标系统规定的最低响应时间或收集频率等. 建议在使用并行收集器时始终开启此选项.
4.4 并发GC参数(响应时间优先)
-XX:+UseConcMarkSweepGC # JDK 5开始提供支持, 以响应时间优先--即缩短Full GC的时间. # JVM 会根据系统配置自行设置使用 ParNewGC & CMS(Serial Old作为替补)收集器. # 建议在 Heap Size 较大且 Full GC 时间较长, 对响应时间的需求大于对吞吐量的需求, 能够承受垃圾回收线程和应用线程共享CPU资源等情况下使用. -XX:+UseCMSCompactAtFullCollection # CMS是不会移动内存的, 此参数设置在每次Full GC后对老年代空间进行压缩整理, 会影响性能, 但是能减少内存碎片. -XX:CMSInitiatingOccupancyFraction=70 # 触发CMS收集器的内存占用阈值, 默认为90%: 当老年代内存空间使用率达到90%时, 就开始对老年代进行CMS并发垃圾收集. # 这个参数设置不当, 将发生promotion failed(晋升失败). -XX:CMSFullGCsBeforeCompaction=10 # 由于并发收集器不对内存空间进行压缩整理, 所以运行一段时间后会产生"碎片", 使得运行效率降低. 此配置项用来设置在几次GC后触发一次内存整理. # 此配置项即将被移除(JDK 8已不建议使用).
4.5 G1 GC参数
-XX:+UseG1GC # 使用G1收集器 -XX:MaxGCPauseMillis=200 # 设置回收器的最大停顿毫秒值, 这是一个概率目标, JVM将尽最大努力去实现它. -XX:G1ReservePercent=15 # 设置堆的临时上限, 以防止因堆扩大失败而导致的异常. 默认值是10. -XX:G1HeapRegionSize=16 # 使用 G1 的 Java 堆细分为大小相等的区域(Region), 此选项是设置单个区域的大小, 默认值是基于堆大小的一种人体工效划分, 最小值是1Mb, 最大值是32Mb. # 人体工效: 根据平台相关的默认选择和根据需求动态垃圾回收的行为统称为人体工效, 人体工效的作用就是可以通过少量的命令行选项就可以让JVM提供最合适的性能.
4.6 通用GC参数
-Xnoclassgc # 禁用类垃圾收集, 能提高性能. -XX:MaxHeapFreeRatio=70 # GC过后堆的最大空闲空间比例, 避免过渡压缩 -XX:MinHeapFreeRatio=40 # GC过后堆的最小空闲空间比例, 避免过度膨胀 -XX:MaxTenuringThreshold=5 # 晋升老年代的最大年龄, 默认为15: 新生代对象在15次 Minor GC 后将被转移至老年代. --- 必须在0-15之间. # 如果设置为0, 等同于去掉了新生代的空间, 新生代对象将会越过 Survivor 区直接进入老年代, 很快就会占满老年代发生Full GC. # 同时, 这在老年代对象较多的应用中却可以提高效率. # 如果将此值调大, 则新生代对象会在 Survivor 区进行多次复制, 即增加了对象在新生代的存活时间. -XX:PretenureSizeThreshold=10 # 晋升老年代的对象的大小, 默认为0. 比如设为10M, 则超过10M的对象将越过 Eden区, 直接存入老年代. -XX:+UseThreadPriorities # 启用本地线程优先级API, 使 java.lang.Thread.setPriority() 生效, 不启用则无效 -XX:+DisableExplicitGC # 禁用写在程序中的 System.gc(), 即禁止开发人员调用 gc() 方法影响性能. -XX:+ExplicitGCInvokesConcurrent # 配置 System.gc() 可以和应用程序一起并发执行. # System.gc() 用来回收不用的内存, 此方法只是"建议" JVM 回收内存, 不能强制回收, 具体回收时机由 JVM 决定. -XX:TargetSurvivorRatio=90 # 允许90%的 Survivor 区被占用(JVM默认为50%), 提高对于 Survivor 区的使用率 -XX:SoftRefLRUPolicyMSPerMB=1 # Soft Reference(弱引用)在虚拟机中比在客户机中存活的时间更长, 其清除频率可用此命令来控制. # 此命令用来指定每 MB 堆空间中 Soft Reference 存活的秒数, 默认值为1000毫秒: 对象的最后一个强引用被收集之后, 存活1秒钟. # 这是个近似值: Soft Reference只会在垃圾收集时才会被清除, 而垃圾收集并不总是发生. 可改为0, 客户机中不使用就立即清除.
4.7 其他说明
- 在内存调优中, 内存设置越大, 处理请求的效率也就越高, 但同时垃圾收集所需要的时间也就越长, 在垃圾收集期间的处理效率肯定会受影响, 因此需要作出相应的权衡.
- 关于 CMS 收集器的 Promotion Failed 和 Concurrent Mode Failure :
- Promotion Failed, 晋升失败: 发生 Young GC 时, Eden 区存活的对象 和 Eden 区的 From 块中存活的对象, 两者的体积超过了 Eden 区中 To 块的大小, Young GC 的悲观策略将使这些存活的对象都迁移到老年代, 而此时老年代的大小不足以容纳这些对象, 从而发生 promotion failed , 程序将暂停很长时间.
- Concurrent Mode Failure, 并发修改失败: 在执行 GC 过程中, 恰好有对象要晋升至老年代, 而此时老年代的空间不足, 从而造成 Concurrent Mode Failure.
- 这两种情况都可能触发 Full GC. 要注意不要一次性占用太多的内存, 或对 JVM 的配置进行一定的优化.
- CMSInitiatingOccupancyFraction的设置技巧: 参考: CMSInitiatingOccupancyFraction计算公式
- 如果想学习Java工程化、高性能及分布式、深入浅出。微服务、Spring,MyBatis,Netty源码分析的朋友可以加我的Java高级交流:854630135,群里有阿里大牛直播讲解技术,以及Java大型互联网技术的视频免费分享给大家。
(Xmx-Xmn) * (1 - CMSInitiatingOccupancyFraction/100) >= (Xmn - Xmn/(SurvivorRatior+2))
进而推断出:
CMSInitiatingOccupancyFraction <= ( (Xmx-Xmn) - (Xmn - Xmn/(SurvivorRatior+2) ) ) / (Xmx-Xmn) * 100
相关推荐
- 甲骨文签署多项大型云协议,其一未来可贡献超300亿美元年收入
-
IT之家7月1日消息,根据甲骨文Oracle当地时间6月30日向美国证券交易委员会(SEC)递交的FORM8-K文件,该企业在始于2025年6月1日的202...
- 甲骨文获TEMU巨额合同,后者大部分基础设施将迁移至Oracle云
-
IT之家6月23日消息,Oracle甲骨文创始人、董事长兼首席技术官LarryEllison(拉里埃里森)在本月早些时候的2025财年第四财季和全财年财报电话会议上表示,Oracle...
- Spring Boot 自定义数据源设置,这些坑你踩过吗?
-
你在使用SpringBoot进行后端开发的过程中,是不是也遇到过这样的问题:项目上线后,数据库连接总是不稳定,偶尔还会出现数据读取缓慢的情况,严重影响了用户体验。经过排查,发现很大一部分原因竟然...
- 一个开箱即用的代码生成器(一个开箱即用的代码生成器是什么)
-
今天给大家推荐一个好用的代码生成器,名为renren-generator,该项目附带前端页面,可以很方便的选择我们所需要生成代码的表。首先我们通过git工具克隆下来代码(地址见文末),导入idea。...
- 低代码建模平台-数据挖掘平台(低代码平台的实现方式)
-
现在来看一下数据连接。·这里是管理数据连接的空间,点击这里可以新增一个数据连接。·输入连接名称,然后输入url,是通过gdbc的方式去连接的数据库,目前是支持mysql、oracle以及国产数据库达梦...
- navicat 17.2.7连接oracle数据库提示加载oracle库失败
-
系统:macOS15.5navicat版本:navicatpremiumlite17.2.7连接oracle测试报错:加载oracle库失败【解决办法】:放达里面找到程序,显示简介里面勾选“使...
- 开源“Windows”ReactOS更新:支持全屏应用
-
IT之家6月17日消息,ReactOS团队昨日(6月16日)在X平台发布系列推文,公布了该系统的最新进展,包括升级Explorer组件,支持全屏应用,从Wine项目引入了...
- SSL 推出采用全模拟内置混音技术的模拟调音台Oracle
-
英国调音台传奇品牌SolidStateLogic宣布推出Oracle——一款采用全模拟内置混音技术的调音台,在紧凑的AWS尺寸机箱内集成了大型调音台的功能。该调音台提供24输入和...
- 47道网络工程师常见面试题,看看有没有你不会的!
-
你们好,我的网工朋友。网络工程师面试的时候,都会被问到什么?这个问题其实很泛,一般来说,你肯定要先看明白岗位需求写的是什么。基本上都是围绕公司需要的业务去问的。但不可否认的是,那些最基础的概念,多少也...
- 汉得信息:发布EBS系统安装启用JWS的高效解决方案
-
e公司讯,从汉得信息获悉,近日,微软官方宣布InternetExplorer桌面应用程序将于2022年6月15日正式停用。目前大部分客户都是使用IE浏览器打开EBS的Form界面,IE停用后,只能使...
- 36.9K star ! 推荐一个酷炫低代码开发平台!功能太强!
-
前言最近在逛github,看看能不能搜罗到一些对自己有帮助的开源软件。不经意间看到一个高star的java开源项目:jeecg-boot。进入在线演示版一看,感叹实在是太牛了!此开源项目不管是给来学习...
- Linux新手入门系列:Linux下jdk安装配置
-
本系列文章是把作者刚接触和学习Linux时候的实操记录分享出来,内容主要包括Linux入门的一些理论概念知识、Web程序、mysql数据库的简单安装部署,希望能够帮到一些初学者,少走一些弯路。注意:L...
- 手把手教你在嵌入式设备中使用SQLite3
-
摘要:数据库是用来存储和管理数据的专用软件,使得管理数据更加安全,方便和高效。数据库对数据的管理的基本单位是表(table),在嵌入式linux中有时候它也需要用到数据库,听起来好难,其实就是几个函数...
- JAVA语言基础(java语言基础知识)
-
一、计算机的基本概念什么是计算机?计算机(Computer)全称:电子计算机,俗称电脑。是一种能够按照程序运行、自动高速处理海量数据的现代化智能电子设备。由硬件和软件组成、没有安装过任何软件的计算机称...
- 再见 Navicat!一款开源的 Web 数据库管理工具!
-
大家好,我是Java陈序员。在日常的开发工作中,常常需要与各种数据库打交道。而为了提高工作效率,常常会使用一些可视化工具进行操作数据库。今天,给大家介绍一款开源的数据库管理工具,无需下载安装软件,基...
你 发表评论:
欢迎- 一周热门
- 最近发表
-
- 甲骨文签署多项大型云协议,其一未来可贡献超300亿美元年收入
- 甲骨文获TEMU巨额合同,后者大部分基础设施将迁移至Oracle云
- Spring Boot 自定义数据源设置,这些坑你踩过吗?
- 一个开箱即用的代码生成器(一个开箱即用的代码生成器是什么)
- 低代码建模平台-数据挖掘平台(低代码平台的实现方式)
- navicat 17.2.7连接oracle数据库提示加载oracle库失败
- 开源“Windows”ReactOS更新:支持全屏应用
- SSL 推出采用全模拟内置混音技术的模拟调音台Oracle
- 47道网络工程师常见面试题,看看有没有你不会的!
- 汉得信息:发布EBS系统安装启用JWS的高效解决方案
- 标签列表
-
- oracle位图索引 (74)
- oracle批量插入数据 (65)
- oracle事务隔离级别 (59)
- oracle 空为0 (51)
- oracle主从同步 (55)
- oracle 乐观锁 (51)
- redis 命令 (78)
- php redis (88)
- redis 存储 (66)
- redis 锁 (69)
- 启动 redis (66)
- redis 时间 (56)
- redis 删除 (67)
- redis内存 (57)
- redis并发 (52)
- redis 主从 (69)
- redis 订阅 (51)
- redis 登录 (54)
- redis 面试 (58)
- 阿里 redis (59)
- redis 搭建 (53)
- redis的缓存 (55)
- lua redis (58)
- redis 连接池 (61)
- redis 限流 (51)