jvm性能调优实战 - 41JVM运行原理和GC原理Review

简介: jvm性能调优实战 - 41JVM运行原理和GC原理Review

Pre

我们已经把完整的JVM运行原理、GC原理以及GC优化的原理,还有线上发生GC问题的各种优化案例分析完了,所以到这里务必停一停脚步,整理一下学习过的知识脉络 。


JVM和GC的运行原理

对于JVM的学习,首先务必要搞清楚一点,JVM是如何运行起来的。

JVM的内存区域划分,最核心的就是这么几块了:年轻代、老年代、Metaspace(也就是以前的永久代)。

其中年轻代又分成了Eden和2个Survivor,默认比例是8:1:1,如下图。

接着我们来思考一下,我们写好的系统会不停的运行,运行的时候是不是就会不停的在年轻代的Eden区域中创建各种对象?

如下图所示。

而且一般创建对象都是在各种方法里执行的,一旦方法运行完毕,方法局部变量引用的那些对象就会成为Eden区里的垃圾对象,就是可以被回收的状态,大家务必要清楚这个过程

接着随着Eden区不断的创建对象,就会逐步的塞满,当然这个时候可能塞满Eden区的对象里大多数都是垃圾对象。一旦Eden区塞满之后,就会触发一次Young GC。

Young GC会采用复制算法,从GC Roots(方法的局部变量、类的静态变量)开始追踪,标记出来存活的对象。

然后把存活对象都放入第一个Survivor区域中,也就是S0区域,如下图所示。

接着垃圾回收器就会直接回收掉Eden区里剩余的全部垃圾对象,在整个这个垃圾回收的过程中全程会进入Stop the Wold状态,也就是暂停系统工作线程,系统代码全部停止运行,不允许创建新的对象

只有这样,才能让垃圾回收器专心工作,找出来存活对象,回收掉垃圾对象,如下图所示。

一旦垃圾回收全部完毕之后,也就是存活对象都进入了Survivor区域,然后Eden区都清空了,那么Young GC执行完毕,此时系统恢复工作,继续在Eden区里创建对象,如下图所示。

下一次如果Eden区满了,就会再次触发Young GC,把Eden区和S0区里的存活对象转移到S1区里去,然后直接清空掉Eden区和S0区中的垃圾对象

当然这个过程中系统是禁止运行的,处于Stop the World状态,如下图所示。

负责Young GC的垃圾回收器有很多种,但是常用的就是ParNew垃圾回收器,他的核心执行原理就如上所述,只不过他运行的时候是基于多线程并发执行垃圾回收的,大家只要记得这点就可以。

这就是最基本的JVM和GC的运行原理,大家都搞懂了吗?


对象什么时候进入老年代?

光是一块年轻代和Young GC配合起来,就足够JVM来使用了吗?

No!

实际JVM运行过程中,有很多意外的情况会发生的,会导致对象进入老年代区域中,如下所述几种情况,反复给大家总结过,务必要记得很清晰:

1. 一个对象在年轻代里躲过15次垃圾回收,年龄太大了,寿终正寝,进入老年代

2. 对象太大了,超过了一定的阈值,直接进入老年代,不走年轻代

3. 一次Young GC过后存活对象太多了,导致Survivor区域放不下了,这批对象会进入老年代

4. 可能几次Young GC过后,Surviovr区域中的对象占用了超过50%的内存,此时会判断如果年龄1+年龄2+年龄N的对象总和超过了Survivor区域的50%,此时年龄N以及之上的对象都进入老年代,这是动态年龄判定规则


上面4个条件就是最常见的对象进入老年代的情况,那种长期存活的躲过15次Young GC的对象毕竟是少数的,大对象一般在特殊情况下会有,对于那种加载大量数据长时间处理以及高并发的场景,很容易导致Young GC后存活对象过多的。

所以对于这些情况,都会导致对象进入老年代中,老年代对象可能会越来越多,如下图所示。


老年代的GC是如何触发的?

一旦老年代对象过多,就可能会触发Full GC,Full GC必然会带着Old GC,也就是针对老年代的GC

而且一般会跟着一次Young GC,也会触发永久代的GC。

大家还记得Full GC触发的几个条件吗?

  • 老年代自身可以设置一个阈值,有一个JVM参数可以控制,一旦老年代内存使用达到这个阈值,就会触发Full GC,一般建议调节大一些,比如92%
  • 在执行Young GC之前,如果判断发现老年代可用空间小于了历次Young GC后升入老年代的平均对象大小的话,那么就会在Young GC之前触发Full GC,先回收掉老年代一批对象,然后再执行Young GC。
  • 如果Young GC过后的存活对象太多,Survivor区域放不下,就要放入老年代,要是此时老年代也放不下,就会触发Full GC,回收老年代一批对象,再把这些年轻代的存活对象放入老年代中

触发Full GC几个比较核心的条件就是这几个,总结起来,其实就是老年代一旦快要搞满了,空间不够了,必然要垃圾回收一次。

老年代的垃圾回收通常建议走CMS垃圾回收器,回收机制比较复杂,此处建议大家自行复兴和总结一下

总之,Old GC的速度是很慢的,少则几百毫秒,多则几秒。所以一旦Full GC很频繁,就会导致系统性能很差,因为频繁要停止系统工作线程,导致系统看起来一直有卡顿的现象。

而且频繁Full GC还会导致机器CPU负载过高,导致机器性能下降,处理请求能力降低。

所以优化JVM的核心就是减少Full GC的频率。


正常情况下的系统

正常情况下的系统,会有一定频率的Young GC,一般在几分钟一次Young GC,或者几十分钟一次Young GC,一次耗时在几毫秒到几十毫秒的样子,都是正常的。

正常的Full GC频率在几十分钟一次,或者几个小时一次,这个范围内都是正常的,一次耗时应该在几百毫秒的样子。

所以大家如果观察自己线上系统就是这个性能表现,基本上问题都不太大。

当然,实际线上系统很多时候回遇到一些JVM性能问题,就是Full GC过于频繁,每次还耗时很多的情况,此时就需要一些优化了。

相关文章
|
算法 网络协议 Java
【JVM】——GC垃圾回收机制(图解通俗易懂)
GC垃圾回收,标识出垃圾(计数机制、可达性分析)内存释放机制(标记清除、复制算法、标记整理、分代回收)
|
缓存 算法 Java
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
这篇文章详细介绍了Java虚拟机(JVM)中的垃圾回收机制,包括垃圾的定义、垃圾回收算法、堆内存的逻辑分区、对象的内存分配和回收过程,以及不同垃圾回收器的工作原理和参数设置。
1255 4
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
|
算法 Java
JVM进阶调优系列(4)年轻代和老年代采用什么GC算法回收?
本文详细介绍了JVM中的GC算法,包括年轻代的复制算法和老年代的标记-整理算法。复制算法适用于年轻代,因其高效且能避免内存碎片;标记-整理算法则用于老年代,虽然效率较低,但能有效解决内存碎片问题。文章还解释了这两种算法的具体过程及其优缺点,并简要提及了其他GC算法。
 JVM进阶调优系列(4)年轻代和老年代采用什么GC算法回收?
|
存储 监控 Java
JVM进阶调优系列(8)如何手把手,逐行教她看懂GC日志?| IT男的专属浪漫
本文介绍了如何通过JVM参数打印GC日志,并通过示例代码展示了频繁YGC和FGC的场景。文章首先讲解了常见的GC日志参数,如`-XX:+PrintGCDetails`、`-XX:+PrintGCDateStamps`等,然后通过具体的JVM参数和代码示例,模拟了不同内存分配情况下的GC行为。最后,详细解析了GC日志的内容,帮助读者理解GC的执行过程和GC处理机制。
|
Arthas 监控 Java
JVM知识体系学习七:了解JVM常用命令行参数、GC日志详解、调优三大方面(JVM规划和预调优、优化JVM环境、JVM运行出现的各种问题)、Arthas
这篇文章全面介绍了JVM的命令行参数、GC日志分析以及性能调优的各个方面,包括监控工具使用和实际案例分析。
1754 3
|
消息中间件 设计模式 安全
多线程魔法:揭秘一个JVM中如何同时运行多个消费者
【8月更文挑战第22天】在Java虚拟机(JVM)中探索多消费者模式,此模式解耦生产与消费过程,提升系统性能。通过`ExecutorService`和`BlockingQueue`构建含2个生产者及4个消费者的系统,实现实时消息处理。多消费者模式虽增强处理能力,但也引入线程安全与资源竞争等挑战,需谨慎设计以确保高效稳定运行。
262 2
|
存储 Java PHP
【JVM】垃圾回收机制(GC)之引用计数和可达性分析
【JVM】垃圾回收机制(GC)之引用计数和可达性分析
315 0
|
12月前
|
Arthas 存储 算法
深入理解JVM,包含字节码文件,内存结构,垃圾回收,类的声明周期,类加载器
JVM全称是Java Virtual Machine-Java虚拟机JVM作用:本质上是一个运行在计算机上的程序,职责是运行Java字节码文件,编译为机器码交由计算机运行类的生命周期概述:类的生命周期描述了一个类加载,使用,卸载的整个过类的生命周期阶段:类的声明周期主要分为五个阶段:加载->连接->初始化->使用->卸载,其中连接中分为三个小阶段验证->准备->解析类加载器的定义:JVM提供类加载器给Java程序去获取类和接口字节码数据类加载器的作用:类加载器接受字节码文件。
985 55
|
Arthas 监控 Java
Arthas memory(查看 JVM 内存信息)
Arthas memory(查看 JVM 内存信息)
985 6
|
7月前
|
存储 缓存 Java
我们来说一说 JVM 的内存模型
我是小假 期待与你的下一次相遇 ~
519 5