深入理解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

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

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

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • Java实现AES加密与解密(秘钥)

    Java实现AES加密与解密(秘钥)

  • 生于MVP,死于PMF

    生于MVP,死于PMF本文的主要内容会按照是什么、为什么以及如何做的逻辑展开,主要包括以下几部分:什么是MVP与PMF;为什么要有MVP与PMF;如何创建MVP;如何验证PMF。什么是MVP与PMFMVP(MinimalViableProduct),意思是最小可行性产品。即通过一个最小化、却可以满足核心需求的产品来测试市场的反应。为了能更好的理解MVP的概念,可参考下图。…

  • xmind 使用教程[通俗易懂]

    1.这是刚刚打开xmind后的界面,在中央有一个中心主题,你可以把它替换成你自己的主题,比如图形推理。2、把光标定位到中心主题上,然后连续按3次Tab键,你会看到上面效果。tab键可以帮助你迅速的建立某个主题的子主题。3、下面你在连续按3次回车键,你就可以看到上面的效果,你可以通过回车键,建立同级主题。4、你自己在试一试,玩一玩者两个键吧!(tab键和enter回车键)5、如何改变主题的分布方式,你还要学习使用“右键”,选择一个主题,然后点击“右键”,你会发现有很多选择。6、选

  • java面试题及答案2020 大汇总

    java面试题及答案2020 大汇总java面试题及答案2020java面试题大汇总百度第一篇java面试题及答案2020先点赞后收藏,以后更新及时看文末后续更新答案,持续更新一面2018/9/11来自于牛客网1、手写ArrayList2、手写进制转换算法,求出一个数的二进制数1的个数3、JAVA基础,equals和==4、多线程方式、threadlocal,各种锁,synchronized和lock5、设计模式、spring类加载方式、实例保存在哪、aopioc、反射机制6、类加载器,双亲委派模

  • system.Exception:端口已被占用1080「建议收藏」

    system.Exception:端口已被占用1080「建议收藏」找出是哪个程序占用了1080端口打开cmd.exe,输入命令:netstat-aon|findstr"1080"1最后一列就是PID了,我的是3104. 要想知道此PID对应什么程序,可以继续输入:tasklist|findstr"4568"1打开任务管理器,在进程里面找下wpscloudsvr.exe,或者在服务里面找PID为3104。…

  • win10如何设置不打开图片的情况下也能预览图片的缩略图

    win10如何设置不打开图片的情况下也能预览图片的缩略图右击此电脑–>属性–>高级系统设置–>点击高级–>点击性能下面的设置–>然后把视觉效果里:显示缩略图,而不是显示图标前的复选框勾上,OK。

发表回复

您的电子邮箱地址不会被公开。

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