GC杂谈之理论入门 JVM堆布局介绍
唐山干废钢挣钱吗_皇冠体育 JVM堆被划分成两个不同的区域:新生代 ( Young )、老年代 ( Old )。新生代 ( Young ) 又被划分为三个区域:Eden、From Survivor、To Survivor,其中两个Survivor区的大小一致。
(堆新生代批发什么建材挣钱_皇冠体育老年代老年代java堆 = 新生代(Young) + 老年代(Old) = 老年代(Old) + Eden + From Survivor + To Survivor)
特殊参数说明:
JVM参数 默认值 说明–XX:NewRatio 2 老年代(Old):新生代的值(Young),默认为2的情况下:老年代占整个堆的2/3,新生代占1/3
–XX:SurvivorRatio 8 Eden:一个Survivor区的值,默认为8的情况下:Eden区占整个新生代的8/10,FromSurvivor和ToSurvivor各占1/10
GC的分类
Minor GC(Young GC): 发生在新生代的垃圾收集工作。新生代几乎是所有对象出生的地方(当然存在例外,如果对象内存分配的时候发现新生代空间不够的时候会将对象直接分配在老年区)。
Java中大部分对象不需要长久存活,因此新生代是GC发生最频繁的地方。简单的GC流程大致是:
Full GC(Major GC):发生在老年代的垃圾收集动作。没有Minor GC那么频繁。且耗时比Minor GC要久的多。
两种GC的触发条件Minor GC:
新生代GC的触发情况很简单,就是当在新生代Eden或者某个Survivor区创建对象内存不够的时候,就会尝试Minor GC。
Full GC:
old空间不足:如果Eden区不足以分配足够的内存给即将创建的大对象,那么大对象会在Old区创建。此时如果Old区内存也不足,那么就会触发Full GC
Young区晋升到Old区的空间不足:在进行Young GC之前,会判断这次Young GC是否安全,这里所谓的安全是当前老年代的剩余空间可以容纳之前 Young GC晋升对象的平均大小,或者可以容纳Young的全部对象,如果结果是不安全的,就不会执行这次 Young GC,转而执行一次Full GC
PermGen Space空间不足
执行 System.gc()、jmap -histo:live 、jmap -dump
Young GC出现Promotion Faliure:当对象的GC年龄达到阈值时,或者To区放不下时,会把该对象复制到 Old区,如果Old区空间不足时,会发生Promotion Faliure,并接下去触发Full GC
如何判断对象是否存活 GC-Garbage Collection。垃圾回收,也就是回收"垃圾"对象。那么如何判断一个对象是否是垃圾对象呢?
当一个对象不被程序中的任何对象引用的时候,我们可以认为该对象是垃圾对象,可以被收集掉。具体算法包括:
引用计数法 每个对象都有一个引用计数器,当有对象引用它时,计数器+1;当引用失效时,计数器-1;任何时刻计数器为0时就是不可能再被使用的。
下图中左图是对象的引用关系,中图有一个引用失效,右图是清理引用计数器=0的对象后。
缺点:
引用和去引用都伴随着加法和减法,影响性能
对于循环引用的对象无法进行回收
关于循环引用的对象无法回收的分析参照下图:
根搜索 根搜索算法的出现,就是为了解决循环引用的时候引用计数法无法判断对象是否可以被回收的问题。
其算法的核心在于,只要对象没有一条到根对象的可达路径,就可以被回收。
那么什么对象才可以认为是根对象呢?
虚拟机栈的栈帧的局部变量表所引用的对象
本地方法栈的JNI所引用的对象
方法区的静态变量和常量所引用的对象
GC算法 Mark-Sweep(标记-清除)算法 分为两个阶段:
标记: 标记出所有存活对象(根对象的所有可达对象)
清除: 统一回收所有没有存活的对象
存在的两个问题:
标记和清除的效率都不高(标记和清除都需要对堆中的所有对象进行遍历),且在GC的时候需要停止整个应用(即发生STOP THE WORLD)
被标记的对象在内存中的位置可能不连续,回收之后可能会导致空间碎片太多
Copying(复制)算法