1.对象怎么才会被判定为垃圾的标准
没有被其他对象引用
方法: 1.引用计数法:通过判断对象的引用数量来决定对象是否可以被回收(每个对象实例都有一个引用计数器,被引用则+1,完成引用则-1),所以任何引用计数为0的对象实例可以被当作垃圾处理;优点:执行效率高,程序执行受影响较小,缺点:对象互相依赖无法作为垃圾回收
2.可达性分析法:通过判断对象的引用链是否可达来决定对象是否可以被回收GC Root根对象
2.如何垃圾回收?
GC的分类:1.Minor GC年轻代。GC 2.FullGC老年代
回收算法:
1.标记-清除算法:从根集合进行扫描,对存活的对象进行标记,对堆内存从头到尾进行线性便利,回收不可达对象内存;缺点:内存碎片化严重
2.标记-整理算法:先标记存活对象,然后移动所有存货的对象,按照内存地址依次排序,然后将末端的内存地址以后的内存全部回收。
3.复制算法:顾名思义就是将一块内存划分为两份,A和B,分为对象面和空闲面,对象在对象面上创建,然后回收时将存活的对象复制到空闲面,然后清空对象面的对象。优点:无内存碎片化,缺点:原本可用的内存降低为一半。
4.分代收集算法:顾名思义,根据老年代和年轻代执行不同的回收算法机制,大大提升效率。
3.回收哪些区域?
1.年轻代:尽可能快速地收集掉那些生命周期短的对象
Eden区和两个Survivor区,大概占比是图下
1.如果eden区满了就会分配到to区域,如果eden又满了,就进行垃圾回收,年轻代用复制算法,将to区域和eden区域存活的对象移到from区域,存活的对象年龄+1(达到一定年龄直接移动到odl区域,默认15),然后清空eden区域和to区域的无用对象,如果eden区域又满了,则继续进行垃圾回收,这次from和eden的对象移动到to区域,然后清空from和eden的无用对象,如此反复。
2.如果在eden区生成的对象太大,直接分配到old老年区
2.老年代:存放生命周期较长的对象
1.执行算法:标记-清理算法或者标记整理算法
执行Full GC和Major GC,Full GC比MinorGC慢,但执行频率低
2.触发Full GC的条件
1.老年代空间不足 2.永久代空间不足(JDK1.7)3.CMS GC出现promotion failed,concurrent mode failure 4.Minor GC晋升到老年代的平均大小大于老年代的剩余空间
4.既然知道怎么回收,那优化试试?
常用的调优参数
-XX:SurvivorRatio:Eden和Survivor的比值,默认8:1
-XX:NewRatio:老年代和年轻代内存大小的比例
-XX:MaxTenuringThreshold:对象从年轻代晋升到老年代经过GC次数的最大阈值
5.垃圾收集器(对应的收集算法)
1.年轻代常见的垃圾收集器
1.Serial收集器(复制算法)
单线程收集,进行垃圾收集时,必须暂停所有工作线程
2.ParNew收集器(复制算法)
多线程收集,其余和serial收集器一样
3.Parallel Scavenge收集器(复制算法)
更多的是关注系统的吞吐量,次要是用户线程的停顿时间,侧重回收
2.老年代常见收集器
1.Serial Old收集器(标记-整理算法)
单线程收集,进行垃圾收集时,必须暂停所有工作线程
2.ParallelOld收集器(标记-整理算法)
多线程,吞吐量优先
3.CMS收集器(标记-清楚算法)
优点:不需要完全stop the world,能和用户线程同时进行;
初始标记:stop the world。并发标记:并发追溯标记,程序不会停顿 并发预清理:查找执行并发标记阶段从年轻代晋升到老年代的对象
3.年轻代和老年代都能用的垃圾收集器
Garbage First收集器(复制+标记-整理算法)
特点:并发和并行,能够分代收集,整合内存空间,防止碎片化,可预测停顿
待写:强引用,软引用,弱引用,虚引用