没有对象的你每天都会new出一堆对象,按照以前的知识我们可以晓得这些new出的对象都是存放在堆中,而堆中总有一天是会被占满的,而且有些不会再用的对象还存放中堆中,当jvm对这些不会再使用的对象在清理时,就开始进行垃圾回收,接下来我们来聊聊怎么区分这个对象是不是垃圾
该对象被其他对象引用一次,该对象的计数器就会加1,如果对象的计数器为0时,该对象就可以被回收了。 弊端 如果两个对象互相引用,如下图所示
这个时候a对象引用了b对象,而b对象又引用了a,这时a被回收的条件就是b被回收,b也同样如此,就产生了类似死锁的情况,从而导致了内存的泄露。
这个是java中采用的回收机制 先了解一个概念 根对象(GC ROOT): 肯定不可以当作垃圾回收的对象,如果一个对象没有被根对象引用,就可以回收 可以作为根对象的对象类型:
扫描堆中的对象,看是否能够沿着GC Root对象为起点的引用链找到该对象,找不到,表示可以回收
不同的引用,对应引用的对象的回收时机不同,接下来介绍一下这几种引用
例如new出来的就是强引用
特点
特点
应用场景
强引用下导致堆空间溢出
软引用下
在这种方式下其实就是使用软引用进行嵌套强引用,也就是SoftReference嵌套byte数组,从而达到软引用的目的,这样一旦出现堆内存不够就会进行释放软引用对象
这个过程中一旦出现了堆空间不够,就会清理软引用对象引用的对象,但是此时软引用对象还在,虽然占据内存比较小,但最好还是清理一下
使用引用队列进行处理,下方代码,关联了软引用队列,软引用关联的对象回收时,软引用对象会加入队列中,从而实现回收
这里我个人的理解就是判断这些软引用有没有引用其他对象,如果没有,则将其在队列中删除,从而将队列对软引用对象的强引用解除掉,从而实现对象的回收
特点
例如Bytebuffer就是需要一个虚引用对象Cleaner,因为ByteBuffer若是在强引用引用结束之后,会对其进行回收,但是此时直接内存不由jvm管理,这就需要把虚引用对象放置在引用队列中,从而实现对直接内存的回收(虚引用对象就是Cleaner,来调用Unsafe的Free memory()来进行释放)
例如A对象重写了finalize(),并且A即将被垃圾回收,会调用finalize方法,将放置一个终结器引用到队列中,会有一个优先级很低的线程会来检查队列中有无需要释放的引用,从而实现对象的回收,这时可进行个人设置的方法,因此可以得出finalize()执行效率挺差的
学习笔记,分段记录一下,如有错误希望大佬们可以在评论区指正,感谢感谢