Minor GC、Major GC和Full GC之间的区别

2018-01-22 10:43:47来源:oschina作者:久违了java人点击

分享

发现网上很多关于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)
Metaspaceused 9048K, capacity 9360K, committed 9600K, reserved 1058816K
class spaceused 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)
Metaspaceused 9048K, capacity 9360K, committed 9600K, reserved 1058816K
class spaceused 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)
Metaspaceused 9055K, capacity 9360K, committed 9600K, reserved 1058816K
class spaceused 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)
Metaspaceused 9055K, capacity 9360K, committed 9600K, reserved 1058816K
class spaceused 1071K, capacity 1152K, committed 1152K, reserved 1048576K
}1 持久代( 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


最新文章

123

最新摄影

闪念基因

微信扫一扫

第七城市微信公众平台