深入理解GC ——MinorGC\MajorGC\FullGC[通俗易懂]

发现网上很多关于GC的文章都自相矛盾,经过长期的积累验证,本文对很多含混的知识点做了严谨的解释,欢迎有理有据的拍砖!HotSpot虚拟机将其物理上划分为两个–新生代(younggeneration)和老年代(oldgeneration)、永久代(PermanentGeneration)-涉及到的术语:Stop-the-world意味着JVM因为要执行GC而停止了…

大家好,又见面了,我是你们的朋友全栈君。

发现网上很多关于GC的文章都自相矛盾,经过长期的积累验证,本文对很多含混的知识点做了严谨的解释,欢迎有理有据的拍砖!

这里写图片描述

HotSpot虚拟机将其物理上划分为两个–新生代(young generation)和老年代(old generation)、永久代(PermanentGeneration)

  • 涉及到的术语:

  • Stop-the-world
    意味着 JVM 因为要执行GC而停止了应用程序的执行。当Stop-the-world发生时,除了GC所需的线程以外,所有线程都处于等待状态,直到GC任务完成。GC优化很多时候就是指减少Stop-the-world发生的时间。
    MinGC\MajorGC都属于Stop-the-world, 那为什么MajorGC耗时较长呢?因为OldGen包含了大量存货下来的对象。

    Stop the World Event – All minor garbage collections are “Stop the
    World” events. This means that all application threads are stopped
    until the operation completes. Minor garbage collections are always
    Stop the World events.Major garbage collection are also Stop the World
    events. Often a major collection is much slower because it involves
    all live objects. So for Responsive applications, major garbage
    collections should be minimized. Also note, that the length of the
    Stop the World event for a major garbage collection is affected by the
    kind of garbage collector that is used for the old generation space.

  • gc进程,负责内存进行管理:

    • Step 1: Marking 标记出unreference object
      这里写图片描述
    • Step 2: Deletion and Compacting
      -1. 释放未被引用的对象
      -2 紧凑内存,是占用的内存在物理上连续,内存分配器持有空内存的地址头部。

这里写图片描述

新生代(Young generation)

绝大多数最新被创建的对象会被分配到这里,由于大部分对象在创建后会很快变得不可到达,所以很多对象被创建在新生代,然后消失。对象从Young generation区域消失的过程我们称之为”minor GC
Minor GC cleans the Young Generation.

新生代构成

新生代是用来保存那些第一次被创建的对象,他可以被分为三个空间

  1. Eden 空间 内存被调用的起点
  2. Survivor 0\Survivor 1 S0——>S1 ;age++

这里写图片描述

老年代(Old generation)

对象没有变得不可达,并且从新生代中存活下来,会被拷贝到这里。其所占用的空间要比新生代多。也正由于其相对较大的空间,发生在老年代上的GC要比新生代少得多。对象从老年代中消失的过程,我们称之为**”major GC“ **

这里写图片描述

MinorGC Vs MajorGC

When the new generation fills up, it triggers a minor collection in which the surviving objects are moved to the old generation. When the old generation fills up, it triggers a major collection which involves the entire object heap.

看到这里,如果你可能有点晕, 记住
MinGC

  1. As minor GCs continue to occure objects will continue to be promoted to the old generation space.
    2.When the eden space fills up, a minor garbage collection is triggered.

minorGC 是清理整合YouGen的过程, eden 的清理,S0\S1的清理都由于MinorGC
Allocation Failure(YoungGen区内存不足,不够调用) 会触发minorGC

MajorGC:
清理整合OldGen的内存空间

Eventually, a major GC will be performed on the old generation which cleans up and compacts that space.

MinorGC Vs FullGC

Major GC 是清理OldGen。
Full GC 是清理整个堆空间—包括年轻代和永久代。

很不幸,实际上它还有点复杂且令人困惑。首先,许多 Major GC 是由 Minor GC 触发的,所以很多情况下将这两种 GC 分离是不太可能的。另一方面,许多现代垃圾收集机制会清理部分永久代空间,所以使用“cleaning”一词只是部分正确。

这使得我们不用去关心到底是叫 Major GC 还是 Full GC,大家应该关注当前的 GC 是否停止了所有应用程序的线程,还是能够并发的处理而不用停掉应用程序的线程。

另外,是什么触发fullGC呢?官网没有给出答案。从实际操作来看:
FullGC触发场景:
1、System.gc

2.promotion failed (年代晋升失败,比如eden区的存活对象晋升到S区放不下,又尝试直接晋升到Old区又放不下,那么Promotion Failed,会触发FullGC)

3.CMS的Concurrent-Mode-Failure 由于CMS回收过程中主要分为四步:
1.CMS initial mark 2.CMS Concurrent mark 3.CMS remark 4.CMS Concurrent sweep。

在2中gc线程与用户线程同时执行,那么用户线程依旧可能同时产生垃圾,
如果这个垃圾较多无法放入预留的空间就会产生CMS-Mode-Failure,
切换为SerialOld单线程做mark-sweep-compact。

4.新生代晋升的平均大小 大于 老年代的剩余空间 (为了避免新生代晋升到老年代失败)

当使用G1,CMS 时,FullGC发生的时候 是 Serial+SerialOld。
当使用ParalOld时,FullGC发生的时候是 ParallNew +ParallOld.

另外值得注意的是:日志里的 “Full”指非YGC的GC的STW次数! Full Gc 才是实际发生fullGC的次数。不要混淆。

{Heap before GC invocations=3 (full 2):
 par new generation   total 30720K, used 27328K [0x00000000f9c00000, 0x00000000fbd50000, 0x00000000fbd50000)
  eden space 27328K, 100% used [0x00000000f9c00000, 0x00000000fb6b0000, 0x00000000fb6b0000)
  from space 3392K,   0% used [0x00000000fb6b0000, 0x00000000fb6b0000, 0x00000000fba00000)
  to   space 3392K,   0% used [0x00000000fba00000, 0x00000000fba00000, 0x00000000fbd50000)
 concurrent mark-sweep generation total 68288K, used 66909K [0x00000000fbd50000, 0x0000000100000000, 0x0000000100000000)
 Metaspace       used 9048K, capacity 9360K, committed 9600K, reserved 1058816K
  class space    used 1071K, capacity 1152K, committed 1152K, reserved 1048576K
10.785: [GC (Allocation Failure) 10.785: [ParNew: 27328K->27328K(30720K), 0.0000174 secs]10.785: [CMS: 66909K->66417K(68288K), 0.1443041 secs] 94237K->86201K(99008K), [Metaspace: 9048K->9048K(1058816K)], 0.1443554 secs] [Times: user=0.16 sys=0.03, real=0.14 secs] 
Heap after GC invocations=4 (full 3):
 par new generation   total 30720K, used 19783K [0x00000000f9c00000, 0x00000000fbd50000, 0x00000000fbd50000)
  eden space 27328K,  72% used [0x00000000f9c00000, 0x00000000faf51de0, 0x00000000fb6b0000)
  from space 3392K,   0% used [0x00000000fb6b0000, 0x00000000fb6b0000, 0x00000000fba00000)
  to   space 3392K,   0% used [0x00000000fba00000, 0x00000000fba00000, 0x00000000fbd50000)
 concurrent mark-sweep generation total 68288K, used 66417K [0x00000000fbd50000, 0x0000000100000000, 0x0000000100000000)
 Metaspace       used 9048K, capacity 9360K, committed 9600K, reserved 1058816K
  class space    used 1071K, capacity 1152K, committed 1152K, reserved 1048576K
}
{Heap before GC invocations=4 (full 4):
 par new generation   total 30720K, used 30719K [0x00000000f9c00000, 0x00000000fbd50000, 0x00000000fbd50000)
  eden space 27328K,  99% used [0x00000000f9c00000, 0x00000000fb6afff8, 0x00000000fb6b0000)
  from space 3392K, 100% used [0x00000000fb6b0000, 0x00000000fba00000, 0x00000000fba00000)
  to   space 3392K,   0% used [0x00000000fba00000, 0x00000000fba00000, 0x00000000fbd50000)
 concurrent mark-sweep generation total 68288K, used 68286K [0x00000000fbd50000, 0x0000000100000000, 0x0000000100000000)
 Metaspace       used 9055K, capacity 9360K, committed 9600K, reserved 1058816K
  class space    used 1071K, capacity 1152K, committed 1152K, reserved 1048576K
11.088: [Full GC (Allocation Failure) 11.088: [CMS11.107: [CMS-concurrent-mark: 0.116/0.144 secs] [Times: user=0.39 sys=0.06, real=0.14 secs] 
 (concurrent mode failure): 68286K->68262K(68288K), 0.1883157 secs] 99006K->98318K(99008K), [Metaspace: 9055K->9055K(1058816K)], 0.1883465 secs] [Times: user=0.22 sys=0.00, real=0.19 secs] 
Heap after GC invocations=5 (full 5):
 par new generation   total 30720K, used 30055K [0x00000000f9c00000, 0x00000000fbd50000, 0x00000000fbd50000)
  eden space 27328K, 100% used [0x00000000f9c00000, 0x00000000fb6b0000, 0x00000000fb6b0000)
  from space 3392K,  80% used [0x00000000fb6b0000, 0x00000000fb959fd0, 0x00000000fba00000)
  to   space 3392K,   0% used [0x00000000fba00000, 0x00000000fba00000, 0x00000000fbd50000)
 concurrent mark-sweep generation total 68288K, used 68262K [0x00000000fbd50000, 0x0000000100000000, 0x0000000100000000)
 Metaspace       used 9055K, capacity 9360K, committed 9600K, reserved 1058816K
  class space    used 1071K, capacity 1152K, committed 1152K, reserved 1048576K
}

持久代( permanent generation ):

也被称为方法区(method area)。PerGen主要存放.class等文件 ,具体内容如下:

  • Methods of a class (including the bytecodes) 也就是类的方法。
  • Names of the classes (in the form of an object that points to a string also in the permanent generation) 类名称,当然也包括Interface\abstract class等等
  • Constant pool information (data read from the class file, see chapter 4 of the JVM specification for all the details).常量池
  • Object arrays and type arrays associated with a class (e.g., an object array containing references to methods).首先要知道数组存放的全部是引用,这里的意思应该是数组中的引用.
  • Internal objects created by the JVM (java/lang/Object or java/lang/exception for instance)
  • Information used for optimization by the compilers (JITs) JIT优化的相关信息

运行时载入,另外,javaSE library classes and methods 也会在这里加载.
permanent Gen 也会在FullGC时回收。

Classes may get collected (unloaded) if the JVM finds they are no longer needed and space may be needed for other classes. The permanent generation is included in a full garbage collection.

老年代GC处理机制

老年代空间的GC事件基本上是在空间已满时发生,执行的过程根据GC类型不同而不同
JDK7一共有5种GC类型:

Serial GC
Parallel GC
Parallel Old GC (Parallel Compacting GC)
Concurrent Mark & Sweep GC (or “CMS”)
Garbage First (G1) GC

jstat -gcutil PID

被用于检查堆间的使用情况,GC执行的次数以及GC操作所花费的时间。
建议使用gcviwer

https://github.com/chewiebug/GCViewer

如果GC执行满足了以下要求,GC并不需要优化:
如需优化请参考:

http://www.oracle.com/technetwork/java/javase/gc-tuning-6-140523.html

Minor GC 执行快 (50 ms内).
Minor GC 执行不频繁 (大概10s 执行一次).
Full GC 执行快 (1 second内).
Full GC 执行不频繁 (10 minutes 一次).

参考原文地址:
http://www.oracle.com/webfolder/technetwork/tutorials/obe/java/gc01/index.html
http://www.oracle.com/webfolder/technetwork/tutorials/obe/java/gc01/index.html

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/129323.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 差分数组模板

    差分数组模板参考于labuladong:论那些小而美的算法技巧:差分数组一、什么时候使用差分数组呢?相信很多人都遇到过这类题:给定一个原数组长度为n,查询次数m,每次查询给定一个区间[l,r]和一个整数k,使得原数组介于[l,r]之间的元素同时增(或减)k输出最终的数组num[8,2,6,3,1]m=2131023注:第一次查询num=83741第二次查询num=1161041最终num=1

    2022年6月7日
    34
  • Java开发经典实战!java编程培训学校排名

    Java开发经典实战!java编程培训学校排名GC概述垃圾收集(GarbageCollection)通常被称为“GC”,由虚拟机“自动化”完成垃圾回收工作。思考一个问题,既然GC会自动回收,开发人员为什么要学习GC和内存分配呢?为了能够配置上面的参数配置?参数配置又是为了什么?“当需要排查各种内存溢出,内存泄露问题时,当垃圾成为系统达到更高并发量的瓶颈时,我们就需要对GC的自动回收实施必要的监控和调节。”JVM中程序计数器、虚拟机栈、本地方法栈3个区域随线程而生随线程而灭。栈帧随着方法的进入和退出做入栈和出栈操作,实现了自动的内存清理。它们的

    2022年7月7日
    30
  • web服务器短信监控服务是什么_手机web服务器在哪打开

    web服务器短信监控服务是什么_手机web服务器在哪打开服务器监控软件可以进行各种服务器的WEB监控,系统将以WEB的用户的身份按用户指定的时间检测您的WEB是否正常,一旦检测到不正常,将以短信/邮件方式报警。如图所示: 图:WEB监控  图:WEB监控日志记录 相关监控功能:PING监控cpu监控内存监控MySQL监控DB2监控流量监控错误监控TCP服务监控

    2025年6月23日
    3
  • Java程序员,你一定需要了解的六款大数据采集平台

    Java程序员,你一定需要了解的六款大数据采集平台随着大数据越来越被重视,数据采集的挑战变的尤为突出。今天为大家介绍几款数据采集平台: ApacheFlume Fluentd Logstash Chukwa Scribe SplunkForwarder 大数据平台与数据采集任何完整的大数据平台,一般包括以下的几个过程: 数据采集 数据存储 数据处理 …

    2022年6月6日
    125
  • 浮雕建模软件_自建房设计软件

    浮雕建模软件_自建房设计软件vectricaspire10是一款非常专业的3d浮雕模型设计软件,为CNC铣床上创建和切割零件提供了强大直观的解决方案,凭借其独特的3D组件建模、完善的2D设计、编辑工具集让你可以轻松使用现有2D数据或导入的3D模型,甚至能够从头开始创建自己的2D和3D零件。而且可以将几何体捕捉到不作为几何体存在的直线,延伸和交叉点,从而减少对大多数构造矢量的需求,还具有一整套完善的绘图工具,允许你通过在创建几何体时允许键入值来更轻松地为形状创建和编辑过程添加更多精度,让你能够更准确地切割这些形状。与此同时,全新的v

    2025年9月13日
    7
  • 设置 node 环境变量

    设置 node 环境变量一、前言下载完node后,想要在编辑器里面使用npm命令,必须设置环境变量。二、设置步骤如下(以win10操作系统为例)1.找到“此电脑”,点击右键,选择“属性”;2.按照下图1、2、3的顺序点击;3.出现如下图,选择“path”;4.出现如下图,选择“新建”;5.出现如下图,选择“浏览”,选择node的安装地址;6.确…

    2022年6月8日
    39

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号