你所不了解的垃圾回收器

垃圾回收器
定义:

​ 垃圾收集器是java虚拟机垃圾收集器提供的一种用于在空闲时间不定时回收无任何对象引用的对象占据的内存空间的一种机制(垃圾回收器会自动的帮我们释放存储空间)

特征:
1.停止-复制

(这个算法效率很高,因为把活着的对象都复制走了,剩下的就是没用的了,直接清理就好,但造成了很多不必要的资源浪费,在垃圾很少的时候也会降低执行效率)

​ 程序首先停止,然后将所有存活对象从一个堆复制到另一个堆,剩下的就是没用的垃圾了,但当一个对象从一个地方移动到另一个地方时,所有指向该对象的引用都必须修改(地址变了所以存在于栈中的引用地址就得改)

这个算法存在的问题:

​ 1.你要有两个堆。然后在这两个独立的堆之间来回复制内存,这比实际需要多了一倍的内存,所以他浪费了内存。

​ 2.一旦程序变的稳定,他可能很少产生垃圾,甚至没有。但复制收集器仍然会将所有内存从一个一个堆复制到另一个堆当中,降低了执行效率。

2.标记-清楚

(这个算法在垃圾很少或没有的时候,速度很快,但在一般情况中算法就很慢)

​ 该算法从栈和静态存储开始,遍历所有引用以查找存活对象。每当他找到一个存活对象,就会给该对象设置一个标记。当标记过程结束后进行清除,在清除过程中,没有被标记的对象被释放,它没有进行对象的复制。

3.分代

​ 创建一个对象的时候,总是在Eden区操作,当这个区满了,那么就会触发一次Young GC,也就是年轻代的垃圾回收。当Eden区再次被用完,就再触发一次Young GC,此时会将Eden区与From区还在被使用的对象复制到To区。在下一次Young GC的时候,则是将Eden区与To区中的还在被使用的对象复制到From区。若干次Young GC后,有些对象在From与To之间来回游荡,一旦超出阈值,就将它们复制到老年代。如果老年代被用完、则执行Full GC

在这里插入图片描述

4.自适应

​ JVM会监控垃圾收集的效率,如果所有对象都很稳定,垃圾收集器效率很低的话,它会切换到“标记–清除”算法。同样,JVM会跟踪标记和清除的效果,如果堆里开始出现很多碎片,它会切换回“停止–复制”算法。

finalize方法

那既然垃圾回收器都这么强大了,那还需要我们进行资源清理工作吗?答案是肯定的,垃圾回收器,只知道回收构造函数创建的对象,但那没用构造函数创建的特殊对象只能我们自己来释放了。垃圾回收器什么时候执行呢,是由我们的jvm虚拟机来判断我们当前的堆内存是否满足触发执行GC的条件。

  • 垃圾回收器在回收某个对象的时候,首先会调用该对象的finalize()方法

finalize()是Object里面的一个方法,当一个堆空间中的对象没有被栈空间变量指向的时候,这个对象会等待被java回收:jdk里面是这样实现的:

protected void finalize() throws Throwable { }
}

在这里插入图片描述

​ 源码中显示的@Deprecated(since="9")的意思就是说在jdk9以后这个方法就过时了(有其他的方法代替)

原因:

​ 《Effective Java》的作者―—Joshua Bloch 认为:“Java语言规范不仅不保证finalize()方法会被及时地执行,而且根本就不保证它们会被执行。”
​ 为什么?――假设用finalize()方法关闭已经打开的文件,由于finalize()方法有可能永远不执行,也可能被延迟执行,就可能导致该文件迟迟未能关闭,甚至永远没有关闭,最终导致大量的文件会保留在打开状态。积累到一定程度,程序就可能再也无法打开文件,导致运行失败!

​ finalize()虽然看起来用于清理资源,但它不能等同于C++的析构函数,它通常会被GC自动调用,由于垃圾收集不一定会执行,因此finalize()方法也不一定会执行。

​ finalize()的使用仅限于一种特殊情况︰对象以某种方式分配存储空间,而不是通过创建对象来分配。假设你的对象在不使用new的情况下分配了一块“特殊”内存。垃圾收集器只知道如何释放由new分配的内存,所以它不知道如何释放对象的这块“特殊”内存。比如未使用Java 的new分配内存,即采用了类似C语言的机制,在Java中,就是使用本地方法来实现,例如通过调用C的malloc()系列函数来分配存储空间。此时,应该在finalize()方法中调用C的free()函数。

资源清理总结

可以总结为∶
1.在Java中始终使用new创建对象,此时,垃圾收集器会自动释放存储空间。

2.如果在Java中通过其他机制创建了本地对象,则使用finalize()管理内存空间的释放,并通过垃圾收集器自动调用。

放存储空间。

2.如果在Java中通过其他机制创建了本地对象,则使用finalize()管理内存空间的释放,并通过垃圾收集器自动调用。

3.如果需要终止对象封装的资源(如文件或线程),请提供一个显式的终止方法.如显式定义close()方法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值