Java GC(垃圾回收机制)
目录
分代回收机制
新生代
绝大多数刚被建立的对象
在建立后很快变得不可达,被 JVM 回收
对象从这个区域被回收的过程称为 Minor GC
回收算法:复制算法
空间分配
一个伊甸园空间(Eden)
两个幸存者空间(From Survivor、To Survivor)
默认新生代空间的分配:Eden : From : To = 8 : 1 : 1
执行顺序
大多数刚被建立的对象会存放在伊甸园空间
伊甸园执行第一次 Minor GC 以后,存活的对象会移动到其中一个幸存者空间
此后每次伊甸园每次 GC 都会将存活的对象堆积到同一个幸存者空间
当一个幸存者空间满了以后,还存活的对象会移动到另外一个幸存者空间,而后清空饱和的那个幸存者空间
在以上步骤中重复N次(N = MaxTenuringThreshold(年龄阀值设定,默认15))依然存活的对象,就会被移动到老年代
从上面的步骤能够发现,两个幸存者空间,必须有一个是保持空的。web
对象在刚刚被建立以后,是保存在伊甸园空间的(Eden)。那些长期存活的对象会经由幸存者空间(Survivor)转存到老年代空间(Old generation)。面试
也有例外出现,对于一些比较大的对象(须要分配一块比较大的连续内存空间)则直接进入到老年代。通常在Survivor 空间不足的状况下发生。算法
老年代
对象没有变得不可达,而且重新生代周期中存活了下来,会被拷贝到这里
该区域分配的空间要比新生代多。
GC次数要比新生代少得多。
对象从老年代中被回收的过程,称为 Full GC 或者 Major GC
Major GC 的时间比 Minor GC 要更长
回收算法:标记-整理算法
持久代
也称为方法区(即Java内存模型中的方法区)
保存类常量以及字符串常量
发生在这个区域的GC事件也被算为Major GC性能优化
发生GC的条件很是严苛,必须符合如下三种条件:svg
1.全部实例被回收
2.加载该类的ClassLoader被回收
3.Class对象没法经过任何途径访问(包括反射)性能
GC 执行时机
新生代的伊甸园空间(Eden)不够存放新对象的时候,执行 Minro GC 。优化
升到老年代的对象大于老年代剩余空间的时候(或者小于的时候被 HandlePromotionFailure 参数强制)执行 Full GC 。3d
回收算法
根搜索算法–基础算法
从 GC ROOT 节点开始,寻找对应的引用节点,找到这个节点后,继续寻找这个节点的引用节点。当全部的引用节点寻找完毕后,构成一张图。没有在图中的节点被认为是没有被引用到的节点,即无用的节点。xml
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLicmbw5yMlJDNhBTMyEWZmlTNwUzMhBjYykjNiFWYkFGZ3gTNk9CX0JXZ252bj91Ztl2Lc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
目前 Java 中能够做为 GC ROOT 的对象有:
1. 栈中引用的对象(本地变量表)
2. 本地方法栈中引用的对象(Native对象)
3. 方法区中静态属性引用的对象
4. 方法区中常量引用的对象
复制算法
复制算法将内存划分为两个区间,一个活动区间,一个空闲区间,其中活动区间存放的是动态分配的对象。
复制算法从根集合扫描活动区间,将存活的对象复制到空闲区间。扫描完毕后,将活动区间清空。把本来的空闲区间变成活动区间。以此循环。
复制算法在存活对象比较少的时候,极为高效,利用空间换来时间。因此复制算法的使用场景,必须是对象的存活率很是低才行,并且最重要的是,咱们须要克服50%内存的浪费。
标记-整理算法
标记-整理算法从根集合进行扫描,对存活的对象进行标记,标记完毕后,再扫描整个空间中未被标记的对象进行直接回收。回收不存活的对象以后,会将全部存活的对象往左端空闲空间移动。避免产生内存碎片。