一、定义
一、如何判断对象是否能够垃圾回收
当垃圾回收时如果内存不够,就会回收软引用对象,不管内存够不够都会回收弱引用对象。
当软引用和弱引用被垃圾回收后,就会将软引用和弱引用放到引用队列中
如果要对这两个引用占用内存进行垃圾回收时,就要扫描引用队列。
虚引用对directmemory进行内存释放过程
首先垃圾回收Bytebuffer引用
然后由于ByteBuffer引用消失,所以虚引用Cleaner直接内存地址进入引用队列
四种引用的概念
什么样的引用是软引用:
应用的场景是当一些不重要的资源需要被引用的时候,我们使用软引用来引用吗,这样当资源缺乏时就可以直接释放软引用,从而达到释放资源的目的。
使用引用队列关联软引用
弱引用
二、垃圾回收算法
1、标记清楚算法
简单的说就是将没有gc root指向的对象全部垃圾回收
缺点:会存在内存碎片
2、标记整理
将没有gc root指向的对象全部垃圾会后
不存在内存碎片但是效率比较低。
3、复制算法
原理是将所有被GC root引用的对象赋值到另一个内存空间,不被GC root引用的对象直接垃圾回收,然后将赋值到另外一个空间的值,全部赋值回原来的内存空间。
优点是不会产生内存碎片,缺点是占用了更多的内存空间。
三、分代垃圾回收机制
分代垃圾回收的工作原理
一开始对象被创建时出现在伊甸园内存中,当伊甸园随着对象的创建满了以后,出发新生代垃圾回收minor GC,这是所有的被Root GC指向的对象都被放到幸存区To中,然后清楚所有伊甸园内存中没有被root GC指向的对象,并且将幸存区To和幸存区From的引用交换,并且将保留下来的对象年龄加1,当年龄到达一定的阈值,这个对象就会被放入老年代内存中。当老年代的内存不够的时候,首先触发minor GC,如果内存还是不够的话,就会触发FULL GC这时会对新生代和老年代同时垃圾回收。
分代垃圾回收的相关VM参数
大对象直接分配到老年代内存中
在新生代空间肯定不足以容纳大对象的时候,大对象会直接晋升到老年代内存中。需要注意的是一个线程内的java堆空间溢出,不会导致主线程的退出但是会报线程的堆内存溢出。
四、垃圾回收器
1、串行垃圾回收器
启动一个线程的垃圾回收
2、吞吐量优先垃圾回收器
采用标记加整理算法进行垃圾回收,启动多个线程进行垃圾回收。
3、响应时间回收的垃圾回收
4、G1垃圾回收器(面试重点):
4.1 young Collection
当新生代的垃圾要垃圾回收的时候,会首先将不能回收的回收的对象放到一个s幸存区这个幸存区也是Regin
当幸存区满了以后就需要将部分到年龄的对象晋升到老年代,部分不到年龄的对象就放到一个新的幸存区中。
4.2Young Collection +CM
其中STW是将所有线程全部停止,进行垃圾回收。
4.3MIXed Collection
进行最终标记,如果一个对象确定需要垃圾回收才进行垃圾回收
4.5 full Gc
4.6Young Collection的跨带引用问题
4.7 Remark
当C对象别B引用完后,可能A后序会引用,这时就要给c进行重标记,这样就可以让c不被垃圾回收
4.8 字符串去重
4.9 类卸载
4.10 回收巨型对象
4.11 并发标记起始时间的调整
JDK9 更高效的回收