![](https://cdn.nlark.com/yuque/0/2021/png/22761450/1635160334384-043220e3-591b-4efc-8e77-dd6c5285e94d.png#from=url&id=Um49v&margin=%5Bobject%20Object%5D&originHeight=654&originWidth=1614&originalType=binary&ratio=1&status=done&style=none) <br />堆由年轻代和老年代组成,其中年轻代包括Eden区和Survivor区。老年代默认占了整个堆3/2,年轻代占了3/ 1。年轻代这几个区域默认8:1:1的比例<br />对象优先放到Eden元区,当Eden元区放不下了,JVM会让字节码执行引擎在后台开启一个垃圾收集线程,执行Minor GC,专门收集内存区域的垃圾对象。判断垃圾的算法有两种,引用计数算法,可达性分析法,现在新的版本基本上都是用可达性分析算法。
可达性分析算法
将“GC Roots”对象作为起点(GC Roots的根节点:线程栈本地变量、静态变量、本地方法栈的变量等),从这些节点开始向下搜索引用的对象,找到的对象都标记为非垃圾对象,其余未被标记的对象都是垃圾对象。
回收过程
他首先会找出所有的GC Roots变量,找到他直接引用对象之后,还会继续往下找,直到找到不在引用其他对象的时候,截至,走过的路径称为引用链。凡是在这个引用链上的所有对象都会被标记为非垃圾对象,从Eden区复制到from区,Eden区剩余的对象就是没有被任何引用,都是垃圾对象,会直接被清除掉。
Eden区被清空后,又可以放新对象了,当Eden区又满了,会再次执行Minor GC ,因为Minor GC是会回收整个年轻代的垃圾,所以Eden和from区的垃圾都会被回收。
当from区中的对象在下一次Minor GC中又是可达性对象,那么它会被复制到to区,其余的非可达性对象也就是垃圾对象会全被干掉。所以在年轻代中,一个对象只要经历一次Minor GC存活下来,它就会在在from或to中移动一次,挪过来挪过去,每挪一次他的分代年龄都会加一,标记着他经历过几次Minor GC,当一个对象的分代年龄达到了15,它会被挪到老年代中。
老年代空间只有在年轻代代对象转入及创建为大对象、大数组时才会出现不足的现象,会发生一次Full GC,耗时很严重,这是我们最需要减少的。当执行Full GC后空间仍然不足,则抛出错误:java.lang.OutOfMemoryError: Java heap space 。为避免以上两种状况引起的FullGC,调优时应尽量做到让对象在Minor GC阶段被回收、让对象在年轻代多存活一段时间及不要创建过大的对象及数组。