分析&回答
- 调用GC并不保证GC实际执行
- finalize抛出的未捕获异常只会导致该对象的finalize执行退出。
- 用户可以自己调用对象的finalize方法,但是这种调用是正常的方法调用,和对象的销毁过程无关。
- JVM保证在一个对象所占用的内存被回收之前,如果它实现了finalize方法,则该方法一定会被调用。Object的默认finalize什么都不做,为了效率,GC可以认为一个什么都不做的finalize不存在。
- 对象的finalize调用链和clone调用链一样,必须手工构造。
protected void finalize() throws Throwable {
super.finalize();
}
finalize使用注意点
- 尽量不要用finalize,太复杂了,还是让系统照管比较好。可以定义其它的方法来释放非内存资源。
- 如果用,尽量简单。
- 如果用,避免对象再生,这个是自己给自己找麻烦。
- 可以用来保护非内存资源被释放。即使我们定义了其它的方法来释放非内存资源,但是其它人未必会调用该方法来释放。在finalize里面可以检查一下,如果没有释放就释放好了,晚释放总比不释放好。
- 即使对象的finalize已经运行了,不能保证该对象被销毁。要实现一些保证对象彻底被销毁时的动作,只能依赖于java.lang.ref里面的类和GC交互了。
反思&扩展
finalize VS System.gc
- finalize方法在垃圾回收器准备垃圾回收前被调用,但是不一定会被调用
- finalize()其实是用来释放不是通过java的new关键字分配的内存比如说通过本地方法调用了c程序,该c程序malloc分配了内存,那么垃圾回收器就不能通过java语言来释放内存,只能在finalize方法内通过本地方法调用c程序进行释放内存
- System.gc()建议垃圾回收器进行垃圾回收,但是不一会立即执行,不管新的对象还是旧的对象都会进行回收,是full gc
对象再生
任何时候,GC都可以从F-Queue中拿到一个Finalizable的对象,标记它为Finalized,然后执行它的finalize方法,由于该对象在这个线程中又可达了,于是该对象变成Reachable了(并且Finalized)。而finalize方法执行时,又有可能把其它的F-Reachable的对象变为一个Reachable的,这个叫做对象再生。
喵呜面试助手: 一站式解决面试问题,你可以搜索微信小程序 [喵呜面试助手] 或关注 [喵呜刷题] -> 面试助手 免费刷题。如有好的面试知识或技巧期待您的共享!