GC,java垃圾收集器。
1.判断垃圾是否可以回收:
引用计数:给对象设一个引用计数器,每当对象多一个引用,计数器加1,当计数器为0时,对象可以当做垃圾;(缺点:存在循环引用的问题,计数器永远不为0,也就无法回收)
可达性:通过GC roots作为起始点进行搜索,不能达到的就可以当做垃圾。(补充:GC roots指的是垃圾回收器对象,包括虚拟机栈中引用的对象、本地方法栈中引用的对象、方法区中类静态属性引用的对象、方法区中常量引用的对象。不是GC roots或者没被GC roots引用的对象可以当做垃圾)
引用类型:前两种方法均与“引用”有关。
强引用(永远不被回收);
弱引用:存活到下一次垃圾回收器工作之前。
软引用:类似于“缓存”的功能。在内存溢出时被回收。
虚引用:一个对象的虚引用不会对其生存时间构成影响,其存在的目的就是为了在对象被回收时收到一个通知。
2.回收主要的是对堆内存(运行时数据区)------分配与回收
堆内存分为新生代、老年代、持久代。新生代又分为Eden(一个)和Survivor(一般两个)。
分配策略:
先对Eden进行分配:空间不足是Minor GC;
大对象直接进入老年代;
长期存活的对象进入老年代;(年龄计数器、一次Minor GC后仍存活且可以被Survivor容纳,移到Survivor年龄加1,后每经历一次Minor GC不被清理,年龄加1,年龄大于等于15(默认),移动到老年区)
动态对象年龄判定:Survivor中同龄的对象总数大于Survivor空间的一半,大于等于该年龄的对象移到老年区
空间分配担保:GC前,检查老年代最大可用连续空间与新生代所有对象空间,前者大,则Minor GC; 否则,检查老年代最大可用连续空间是否大于历次晋升到老年代对象的平均大小,大于的话Minor GC,小于的话,Full GC。
3.GC算法
标记-清除;要清除的对象做标记
标记-整理;存活的对象向一端移动,边界以外的对象清除
复制算法;内存分两块;使用一块,这一块用完了将存活的对象复制到另一块,并将原来那块进行清理。(常用来回收新生代,一块Eden和两块Survivor,每次用一块Survivor,回收时将Eden和已使用的Survivor中农存活的对象移到另一Survivor)
4.垃圾收集器的比较
收集器 | 串行、并行、并发 | 新生代/老年代 | 收集算法 | 目标 | 适用场景 |
Serial | 串行 | 新生代 | 复制算法 | 响应速度优先 | 单cpu下的Client模式 |
Serial Old | 串行 | 老年代 | 标记-整理算饭 | 响应速度优先 | 单cpu下的Client模式、CMS的后备预案 |
ParNew | 并行 | 新生代 | 复制算法 | 响应速度优先 | 多CPU环境时在server模式下与cms配合 |
Parallel Scavenge | 并行 | 新生代 | 复制算法 | 吞吐量优先 | 在后台运算而不需要太多交互的任务 |
Parallel Old | 并行 | 老年代 | 标记-整理算法 | 吞吐量优先 | 在后台运算而不需要太多交互的任务 |
CMS | 并发 | 老年代 | 标记-清除 | 响应速度优先 | 集中在互联网站或B/S系统服务端上的java应用 |
GI | 并发 | both | 标记-整理 + 复制算法 | 响应速度优先 | 面向服务器端应用,将来替换CMS |
5.Full GC触发条件:
system.gc():建议进行full gc,但是并非一定执行
老年代空间不足:大对象直接进入老年代、长期存活的放入老年代,full gc后仍然空间不足,会抛出错误java.lang.OutOfMemooryError.
空间分配担保失败:使用复制算法的Minor GC需要老年代做担保
JDK1.7及以前,永久代空间不足:存放一些calss信息、静态变量、常量等,当系统中加载的类、反射的类、调用的方法较多时,空间有可能被占满,在没有配置CMS GC的情况下,会执行Full GC
Concurrent Mode Failure:在执行CMS GC的过程中同时有对象放入老年代,而此时老年代空间不足(CMS GC时,当前的浮动垃圾过多导致暂时性的空间不足触发Full GC)