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


相关推荐

  • android visible invisible和gone差异

    android visible invisible和gone差异

  • 蓝牙中的sbc_蓝牙sbc格式和aac差别

    蓝牙中的sbc_蓝牙sbc格式和aac差别在之前《小米的试用哲学:小米AirDots青春版和Redmi红米AirDots无线耳机体验》中,我提到了这两款耳机都支持aptXHD。不过在这两款耳机上,也仅仅支持了aptXHD这个技术,也需要配合高通骁龙手机使用,iOS也就别想了……经过实际测试,这两款耳机均不支持aptXHD技术,在此更正,并对造成的误解致歉!这两款耳机支持SBC、AAC两种编码。小米AirDots青春版和Redmi红…

  • easyui window refresh 刷新两次解决办法

    easyui window refresh 刷新两次解决办法这样写刷新两次$("#changeMwsAccountWin").window(‘refresh’,"adsfasdf.php"’);$("#changeMwsAccountWin").window(‘open’); 这样写刷新一次$("#changeMwsAccountWin").window(‘open’);$("#changeMwsAccountWin").wi…

  • 服务器灾备解决方案–两地三中心(图文详解)[通俗易懂]

    服务器灾备解决方案–两地三中心(图文详解)[通俗易懂]说明两地三中心:两地是指同城、异地三中心是指生产中心、同城容灾中心、异地容灾中心。备端在线两地三中心灾备方案网络设计如下:容灾系统衡量指标衡量容灾系统的主要指标有RPO(RecoveryPointObject):灾难发生时允许丢失的数据量RTO(RecoveryTimeObjective):系统恢复的时间容灾半径:生产系统和容灾系统之间的距离ROI(R…

  • Java 网络IO编程总结(BIO、NIO、AIO均含完整实例代码)

    Java 网络IO编程总结(BIO、NIO、AIO均含完整实例代码)本文会从传统的BIO到NIO再到AIO自浅至深介绍,并附上完整的代码讲解。1、BIO编程1.1、传统的BIO编程网络编程的基本模型是C/S模型,即两个进程间的通信。服务端提供IP和监听端口,客户端通过连接操作想服务端监听的地址发起连接请求,通过三次握手连接,如果连接成功建立,双方就可以通过套接字进行通信。传统的同步阻塞模型开发中,ServerSocket负责绑定IP地址,启动监听端口;Socket负责发起连接操作。连接成功后,双方通过输入和输出流进行同步阻塞式通信。

  • Mysql5.7版本中数据表字段可用的类型

    Mysql5.7版本中数据表字段可用的类型

发表回复

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

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