searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

JVM调优-JVM基础及垃圾回收过程简介

2023-10-07 08:38:55
3
0

JDK体系结构和JVM整体架构解析

JDK体系结构

JVM虚拟机组成

JVM可以分为3大部分:类加载器(类装载子系统),运行时数据区和执行引擎。  

类加载器:

  • 负责加载字节码文件,即java编译后的 .class 文件
  • 负责查找并装载类型

运行时数据区:

  • 负责存放.class 文件,分配内存。运行时数据区又分为5个部分:
    • 方法区:负责存放.class 文件,方法区里有一块区域是运行时常量池,用来存放程序的常量、静态变量、类信息
    • 堆:分配给对象的内存空间。

方法区和堆是所有线程共享的内存空间。

  • 栈(线程):每个线程独享的内存空间;不同的线程都有自己的栈内存空间,可以用来放内部的局部变量。
  • 本地方法栈:本地native方法独享的内存空间,(使用C或者C++实现的)
  • 程序计数器:记录线程执行的位置,方便线程切换后再次执行。

栈(线程),本地方法栈,程序计数器是每个线程独享的。

执行引擎:

  • JAVA虚拟机的最核心组件之一,它负责执行虚拟机的字节码,现代虚拟机为了提高执行效率,会使用即时编译技术将方法编译成机器码后再执行。

GC回收过程

YGC过程:

  • 绝大多数刚创建的对象会被分配在Eden区(伊甸园区),其中的大多数对象很快就会消亡。Eden区是连续的内存空间,因此在其上分配内存极快;
  • 当Eden区满的时候,执行Minor GC(YGC),将消亡的对象清理掉,并将剩余的对象复制到一个存活区Survivor0(此时,Survivor1是空白的,两个Survivor总有一个是空白的);
  • 此后,每次Eden区满了,就执行一次Minor GC,并将剩余的对象都添加到Survivor0;
  • 当Survivor0也满的时候,将其中仍然活着的对象直接复制到Survivor1,以后Eden区执行Minor GC后,就将剩余的对象添加Survivor1(此时,Survivor0是空白的)。
  • 当两个存活区切换了几次(HotSpot虚拟机默认15次,用-XX:MaxTenuringThreshold控制,大于该值进入老年代)之后,仍然存活的对象(其实只有一小部分,比如,我们自己定义的对象),将被复制到老年代。

PS:虚拟机并不是永远地要求对象的年龄必须达到了MaxTenuringThreshold才能晋升老年代。

对象动态年龄判断:如果在Survivor空间中相同年龄所有对象大小的总和大于Survivor空间的50%(-XX:TargerSurvivorRatio可以指定),年龄大于或等于该年龄的对象就可以直接进入老年代,无须等到MaxTenuringThreshold中要求的年龄。例如:Survivor区域现有一批对象,年龄1+年龄2+年龄n的多个年龄对象总和超过了Survivor区域的50%,此时就会吧年龄n(含)以上的对象都放到老年代。这个规则其实是希望那些可能是长期存活的对象,尽早进入老年代。对象动态判断机制一般是在mimor gc之后触发的。

Full GC的触发条件

对于Minor GC,其触发条件非常简单,当 Eden 空间满时,就将触发一次 Minor GC。而 Full GC 则相对复杂,有以下条件:

  • 调用 System.gc()

    只是建议虚拟机执行 Full GC,但是虚拟机不一定真正去执行。不建议使用这种方式,而是让虚拟机管理内存。

  • 老年代空间不足

    老年代内存空间满了之后执行。

    老年代空间不足的常见场景为前文所讲的大对象直接进入老年代、长期存活的对象进入老年代等。

    为了避免以上原因引起的 Full GC,应当尽量不要创建过大的对象以及数组。除此之外,可以通过 -Xmn 虚拟机参数调大新生代的大小,让对象尽量在新生代被回收掉,不进入老年代。还可以通过 -XX:MaxTenuringThreshold 调大对象进入老年代的年龄,让对象在新生代多存活一段时间。

  • 空间分配担保失败

    使用复制算法的 Minor GC 需要老年代的内存空间作担保,如果担保失败会执行一次 Full GC。

  • JDK 1.7 及以前的永久代空间不足

    在 JDK 1.7 及以前,HotSpot 虚拟机中的方法区是用永久代实现的,永久代中存放的为一些 Class 的信息、常量、静态变量等数据。

    当系统中要加载的类、反射的类和调用的方法较多时,永久代可能会被占满,在未配置为采用 CMS GC 的情况下也会执行 Full GC。如果经过 Full GC 仍然回收不了,那么虚拟机会抛出 java.lang.OutOfMemoryError。

    为避免以上原因引起的 Full GC,可采用的方法为增大永久代空间或转为使用 CMS GC。

  • Concurrent Mode Failure

    执行 CMS GC 的过程中同时有对象要放入老年代,而此时老年代空间不足(可能是 GC 过程中浮动垃圾过多导致暂时性的空间不足),便会报 Concurrent Mode Failure 错误,并触发 Full GC。

垃圾收集器:

0条评论
0 / 1000
Mr. 油
89文章数
0粉丝数
Mr. 油
89 文章 | 0 粉丝
原创

JVM调优-JVM基础及垃圾回收过程简介

2023-10-07 08:38:55
3
0

JDK体系结构和JVM整体架构解析

JDK体系结构

JVM虚拟机组成

JVM可以分为3大部分:类加载器(类装载子系统),运行时数据区和执行引擎。  

类加载器:

  • 负责加载字节码文件,即java编译后的 .class 文件
  • 负责查找并装载类型

运行时数据区:

  • 负责存放.class 文件,分配内存。运行时数据区又分为5个部分:
    • 方法区:负责存放.class 文件,方法区里有一块区域是运行时常量池,用来存放程序的常量、静态变量、类信息
    • 堆:分配给对象的内存空间。

方法区和堆是所有线程共享的内存空间。

  • 栈(线程):每个线程独享的内存空间;不同的线程都有自己的栈内存空间,可以用来放内部的局部变量。
  • 本地方法栈:本地native方法独享的内存空间,(使用C或者C++实现的)
  • 程序计数器:记录线程执行的位置,方便线程切换后再次执行。

栈(线程),本地方法栈,程序计数器是每个线程独享的。

执行引擎:

  • JAVA虚拟机的最核心组件之一,它负责执行虚拟机的字节码,现代虚拟机为了提高执行效率,会使用即时编译技术将方法编译成机器码后再执行。

GC回收过程

YGC过程:

  • 绝大多数刚创建的对象会被分配在Eden区(伊甸园区),其中的大多数对象很快就会消亡。Eden区是连续的内存空间,因此在其上分配内存极快;
  • 当Eden区满的时候,执行Minor GC(YGC),将消亡的对象清理掉,并将剩余的对象复制到一个存活区Survivor0(此时,Survivor1是空白的,两个Survivor总有一个是空白的);
  • 此后,每次Eden区满了,就执行一次Minor GC,并将剩余的对象都添加到Survivor0;
  • 当Survivor0也满的时候,将其中仍然活着的对象直接复制到Survivor1,以后Eden区执行Minor GC后,就将剩余的对象添加Survivor1(此时,Survivor0是空白的)。
  • 当两个存活区切换了几次(HotSpot虚拟机默认15次,用-XX:MaxTenuringThreshold控制,大于该值进入老年代)之后,仍然存活的对象(其实只有一小部分,比如,我们自己定义的对象),将被复制到老年代。

PS:虚拟机并不是永远地要求对象的年龄必须达到了MaxTenuringThreshold才能晋升老年代。

对象动态年龄判断:如果在Survivor空间中相同年龄所有对象大小的总和大于Survivor空间的50%(-XX:TargerSurvivorRatio可以指定),年龄大于或等于该年龄的对象就可以直接进入老年代,无须等到MaxTenuringThreshold中要求的年龄。例如:Survivor区域现有一批对象,年龄1+年龄2+年龄n的多个年龄对象总和超过了Survivor区域的50%,此时就会吧年龄n(含)以上的对象都放到老年代。这个规则其实是希望那些可能是长期存活的对象,尽早进入老年代。对象动态判断机制一般是在mimor gc之后触发的。

Full GC的触发条件

对于Minor GC,其触发条件非常简单,当 Eden 空间满时,就将触发一次 Minor GC。而 Full GC 则相对复杂,有以下条件:

  • 调用 System.gc()

    只是建议虚拟机执行 Full GC,但是虚拟机不一定真正去执行。不建议使用这种方式,而是让虚拟机管理内存。

  • 老年代空间不足

    老年代内存空间满了之后执行。

    老年代空间不足的常见场景为前文所讲的大对象直接进入老年代、长期存活的对象进入老年代等。

    为了避免以上原因引起的 Full GC,应当尽量不要创建过大的对象以及数组。除此之外,可以通过 -Xmn 虚拟机参数调大新生代的大小,让对象尽量在新生代被回收掉,不进入老年代。还可以通过 -XX:MaxTenuringThreshold 调大对象进入老年代的年龄,让对象在新生代多存活一段时间。

  • 空间分配担保失败

    使用复制算法的 Minor GC 需要老年代的内存空间作担保,如果担保失败会执行一次 Full GC。

  • JDK 1.7 及以前的永久代空间不足

    在 JDK 1.7 及以前,HotSpot 虚拟机中的方法区是用永久代实现的,永久代中存放的为一些 Class 的信息、常量、静态变量等数据。

    当系统中要加载的类、反射的类和调用的方法较多时,永久代可能会被占满,在未配置为采用 CMS GC 的情况下也会执行 Full GC。如果经过 Full GC 仍然回收不了,那么虚拟机会抛出 java.lang.OutOfMemoryError。

    为避免以上原因引起的 Full GC,可采用的方法为增大永久代空间或转为使用 CMS GC。

  • Concurrent Mode Failure

    执行 CMS GC 的过程中同时有对象要放入老年代,而此时老年代空间不足(可能是 GC 过程中浮动垃圾过多导致暂时性的空间不足),便会报 Concurrent Mode Failure 错误,并触发 Full GC。

垃圾收集器:

文章来自个人专栏
存储专栏
89 文章 | 1 订阅
0条评论
0 / 1000
请输入你的评论
0
0