深入理解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)
上一篇 2022年4月15日 上午9:40
下一篇 2022年4月15日 上午10:00


相关推荐

  • unity安装使用教程_免费版签名

    unity安装使用教程_免费版签名1、进入Unity官网,滑动到最底部,点击“所有版本”:

    2022年4月19日
    73
  • docker端口映射成功 不可用_docker启动后访问拒绝连接

    docker端口映射成功 不可用_docker启动后访问拒绝连接情境描述创建一个docker容器,并进行端口映射。容器启动后,在部署容器的主机上可以访问映射端口,但是其他主机无法访问。问题排查出现上述情况,应是请求被拦截。出现该问题的可能是由于firewall配置异常、ip转发关闭、iptables服务拦截了请求排查firewall(1)使用firewall-cmd–state查看防火墙运行情况如果防火墙处于notrunning,则可以排除…

    2022年10月17日
    5
  • C语言中define的用法详解

    C语言中define的用法详解宏 无非就是定义一个替换的量 好比 definePI3 这样的功能 再深一点就是写一个类似函数的定义 好比 defineMAX a b a gt b a b 这样的功能 下面讲解一下具体用法 一 简单的 define 定义 defineMAXTIM 一个简单的 MAXTIME 就定义好了 它代表 1000 如果在程序里面写 if i

    2026年3月19日
    2
  • 备份从android到ios系统文件,如何将音乐从安卓设备转移到iOS设备中「建议收藏」

    备份从android到ios系统文件,如何将音乐从安卓设备转移到iOS设备中「建议收藏」这几天,小编刚从Android手机切换到iPhone,可是Android手机上还有很多音乐文件没有保存下来,这时候该怎么处理呢?好在,小编发现了一款神器——iMazing,它可以帮助我们顺利的转移各种文件,音乐文件也是不在话下,下面就和小编一起来看看具体该怎么操作吧!图1iPhone将Android手机中的音乐文件转移到电脑中如果大家使用的是Mac电脑,需要到Android官方网站下载Andor…

    2026年1月15日
    4
  • C语言中的void的理解

    C语言中的void的理解1初学者对C/C++语言中的void及void指针类型不甚理解,因此在使用上出现了一些错误。本文将对void关键字的深刻含义进行解说,并详述void及void指针类型的使用方法与技巧。2.void的含义void的字面意思是“无类型”,void*则为“无类型指针”,void*可以指向任何类型的数据。void几乎只有“注释”和限制程序的作用,因为从来没有人会定义一个void变量,

    2022年5月18日
    61
  • 豆包上线字节跳动最新图像创作模型Seedream 4.0

    豆包上线字节跳动最新图像创作模型Seedream 4.0

    2026年3月12日
    2

发表回复

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

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