简介
Java进程在启动后会创建垃圾回收线程,对内存中无用的对象进行回收,

垃圾回收的时机
1,System.gc(),此方法的调用是建议JVM进行FGC(Full GC),并非一定,但是在很多情况下它会触发FGC
2,由垃圾回收机制决定:创建对象时需要分配内存,如果空间不足,就会触发GC; 其他回收机制
java.long.object中的finailize()方法,jvm确定存在没有引用指向该对象时,垃圾回收器就会调用这个方法,标志着这个对象即将死亡,JVM即将回收这个对象,手动调用是不会造成这个方法的死亡的。

垃圾回收策略(判断这个对象是否死亡)
1,引用计数算法:在对象中加入一个引用计数器,当引用这个对象的时候,引用计数器加1,当引用失效的时候,引用计数器减1,当引用计数器为0时,就回收这个对象(它是不能被使用的)
优点:实现简单,效率高。
缺点:很难解决对象之间的相互引用。(Python)
2,可达性分析算法:将GC roots作为引用链的根节点,顺着这引用链往下找,如果要找 对象在引用链上,这个对象是可以使用是,否则的话,就不会被使用 (Java)

需要垃圾回收的内存
jdk1.7中是方法区,jdk1.8中是(元空间):这个区域是永久代,主要回收两部分:1,废弃的常量,2,无用的类,“性价比比较低”

Java堆是垃圾回收的主要区域,细分为:老年代和新生代,新生代可分为eden区,from Survivor区,to Survivor区,新生代的垃圾回收被称为YGC,此空间的Java对象大多都是朝生夕灭,因此,minorGC回收的频率高,回收速度很快。
老年代垃圾回收被称为FGC,majorGC的速度比minorGC慢上10以上。

垃圾回收算法

标记清除算法(老年代):分为“标记”和“清除”两个阶段,标记出所有需要回收的对象,然后回收这些被标记的对象
不足:1,效率问题 2,空间问题(产生大量不连续的内存空间)

复制算法(新生代):将内存划分为大小相等的两块,每次只使用一块,当这块内存用完了就将活着的对象复制到另一块,然后再把使用过的内存清理掉
优点:1,每次回收回收的是一半内存,分配时不考虑碎片化问题,实现简单运行高效
不足:代价有点高,将内存缩小为原来的一半。

标记整理算法(老年代):标记需要回收的位置,整理的话是这样子的,让所有活着的对象都移向一端,清理掉端界之外的内存

分代收集算法:根据存活周期的不同,将内存划分为几个区间
新生代中的98%对象都是朝生夕死的,根据概率统计,将新生代划分为8:1:1,每次新生代可用内存为新生代的90%
在新生代中,每次垃圾回收都会有大量的对象死去,只有少量存活,因次,用复制算法,老年代中对象存活率高,没有额外的内存担保,就必须采用标记清理或是标记整理

垃圾回收的过程

对象在新生代Eden中分配,当Eden不足时,虚拟机发生一次Minor GC.
Eden空间不足,触发Minor GC (将Eden和fromSurvivor中还存在的对象复制到toSurvivo中,最后清理掉Eden和fromSurvivor)
垃圾回收结束后用户线程继续创建并分配 在Eden区,,Eden空间不足时,重复上部分操作

内存分配与回收策略

1,对象优先在Eden区分配
2.大对象直接进入老年代(经常出现大对象的话,会导致内存还有不少,仍让触发GC进行回收)
3长期存活的对象将进入老年代
4,动态年龄判定
5,空间分配担保

垃圾回收的影响

用户线程暂停;(SWT) 垃圾回收工作是在垃圾回收线程中执行的,很多情况下执行垃圾回收工作需要暂停线程
垃圾回收第一步工作是标记,如果用户线程工作的话,可能会把已标记的对象,重新放入引用连

类加载完成的时候虚拟机就把对象内什么偏移量上是什么类型的数据算出来,在编译过程中,在特定位置记录下栈和寄存器中的那些位置是引用,GC在扫描的 时候就可以直接得知这些信息
程序在执行的时候并不是在所有位置都停下开始GC,而是在安全点的位置上停下来进行GC

吞吐量和停顿时间

用户优先:用户线程单次停顿时间短,总的停顿时间长
吞吐量优先:用户线程总的停顿时间短,单次停顿时间长

垃圾收集器

G1收集器(全区域的垃圾回收器)

把堆划分为很多的region块,然后并行的对其进行垃圾回收
G1进行垃圾回收的时候基本不会STW,而是基于most garbage优先回收
用户体验优先
无论如何,G1收集器采用的算法意味着一个region是Eden,存活区,或者老年代 还有H块
在G1中年轻代的垃圾收集使用复制算法,老年代的收集分为四个阶段,初始标记阶段,并发标记阶段,clean up阶段 最终标记阶段,筛选阶段