1.什么是垃圾回收(GC)?
垃圾回收(Garbage Collection)是Java虚拟机(JVM)垃圾回收器提供的一种用于在空闲时间不定时回收无任何对象引用的对象占据的内存空间的一种机制。
注意:垃圾回收回收的是无任何引用的对象占据的内存空间而不是对象本身。换言之,垃圾回收只会负责释放那些对象占有的内存。对象是个抽象的词,包括引用和其占据的内存空间。当对象没有任何引用时其占据的内存空间随即被收回备用,此时对象也就被销毁。但不能说是回收对象,可以理解为一种文字游戏。
2.如何判断那些是垃圾?
这个问题牵扯出两个东西,引用计数和可达性分析
引用计数:在每个对象身上带个引用数,每有其他对象引用他一次,它的计数器就加1,如果引用数为0,那就被标记为垃圾,但它牵扯出一个问题,如果两个对象互相引用,但其实根节点早就已经获取不到他们了,对他们也没有引用了,这时这两个对象就造成了内存泄漏,永远无法被回收了,这就是循环依赖问题
可达性分析:也是java中使用的,做法为,从GC Root为起点,依次向下对整个引用链进行标记,未被标记到的数据就是垃圾数据
3.怎样回收对象?
回收对象有三个算法,标记清除算法,标记整理算法和复制算法
标记清除算法:用可达性分析将对象打上标记,然后将所有没有打上标记的对象进行回收。但由于内存是一块一块申请的空间,但对象有大有小,申请的空间也就有大有小,数据被清除后,空闲空间也会有大有小,就会造成内存碎片化很严重。
标记整理算法:为了解决标记清除算法的碎片化问题,延伸出了标记整理算法,本质就是在标记清除算法清除对象后,对所有对象进行整体重新排序。这个算法也有自己的问题,就是每次整理的时间很长。
复制算法:为了解决标记整理算法的执行时间过长的问题,延伸出了复制算法,本质就是将数据分为两片区域,A区域进行数据整理,清除过后直接将剩下的所有数据转移到B区,也就避免了数据整理。此算法的问题也是一目了然,就是需要更大的内存空间。
JVM年轻代:年轻代采用的也是复制算法不过它有三片空间,Eden,Survivor1,Survivor2,大小比例为8:1:1。如此设计的原因是因为java中的大多数对象都是朝生夕死的,像原有的复制算法一样申请两块完全一样大的空间有些资源浪费。具体用法:新创建的对象默认会进入Eden区,Young GC时,会将剩余数据放入survivor1然后所有对象age+1,然后清空survivor2和Eden区,第二次,会将剩余数据放入survivor2然后所有对象age+1,清空survivor1和Eden区,以此类推。
我们回到JVM中来,堆中将自身分为了两大片区域,分别为新生代和老年代,默认内存比例为1:2
新生代:采用复制算法,将自身分为了三块区域,Eden,survivor1,survivor2,内存占比8:1:1。
老年代:一般采用标记整理算法,CMS收集器默认采用标记清除算法。
4.如何晋升老年代?
1.新生代数据年龄到达15(此为默认值,可通过-XX:MaxTernuringThreshold=参数更改),年龄增加方式为,每转换一次survivor区将对象age+1。
2.动态年龄判断机制:是将survivor区域所有对象从小到大内存相加,如果加到N的时候发现占到了survivor区域的一半内存,就将N和N以上年龄的对象放入老年代。
3.大对象:可通过JVM参数设置大小。
4.在Young GC后发现survivor区放不下,就会直接升级到老年代。
5.老年代分配担保机制
什么是老年代分配担保机制?
记录每次Young GC后晋升老年代的数据大小,因为Young GC会对老年代剩余空间进行分析,判断年轻代所有对象是否大于老年代剩余的连续空间,如果大于需要调用Full GC让老年代先清理出足够的空间,分配担保机制的作用就是,对记录下来的历史晋升数据进行一个平均,用这个平均值来判断老年代是否能承载年轻代的晋升,减少不必要的Full GC。
如果真的造成了老年代的溢出,会抛出OOM异常。
6.收集器(这里只对收集器进行简单介绍,具体的还是要看对应收集器的文章)
1.Serial收集器:分新生代和老年代,新生代采用复制算法,老年代采用标记整理算法,单线程运行,运行时Stop the word。
2.ParNew收集器:ParNew是新生代收集器,为serial新生代的多线程版本,也采用复制算法,运行时Stop the word。
3.Parallel收集器:新生代和老年代都有,为多线程收集器,可以设置每次GC的时间大小,时间占比,来保证吞吐量问题,将GC变为碎片执行,可以通过自身分析,减少配置不同区域的参数,只要配置堆的大小他会结合分析自动分配空间。JDK1.8中默认为此收集器。
4.CMS收集器:新生代采用复制算法,老年代默认采用标记清除算法,分多步执行,有并发执行阶段,采用三色标记算法。
5.G1收集器:G1全部采用复制算法,引入了Region概念,此收集器最为繁琐,如需了解请移步。