垃圾回收器是否忽略异常?

4
我正在阅读的是Java中不要使用finalize方法的原因。该文章指出,GC线程会忽略由finalize方法引发的任何异常,并且不会进一步传播它们,那么为什么需要忽略呢?
此外,该对象的终结意味着该对象已经被清理,这是否意味着该对象始终存在于内存中?

1
finalize方法传播出来的异常将被忽略。实质上,运行finalize方法,无论它是以“正常”结束还是以异常结束,对象都会被标记为不再尝试进行终结。在下一个GC周期中,将忽略终结器并收集该对象(如果它不再被引用)。 (终结器可能会使其重新引用。) - Hot Licks
3个回答

2

它忽略了异常,因为它没有处理异常的手段。finalize()方法的目的是在对象死亡之前进行最后的清理工作。如果您想在finalize()方法中处理异常,则需要添加代码来实现。


如果垃圾回收器忽略了异常和对象的终结,那么这是否意味着该对象始终驻留在内存中? - Vishrant
@Vishrant 最终器线程不会向GC发送任何信息,因此异常无法干扰任何内容。 - Peter Lawrey
3
@Vishrant,垃圾回收器与 finalize 线程是独立工作的。当垃圾回收器运行时,它只会收集那些不再被强引用并且不需要使用 finalize() 方法的对象。finalize 线程则会忽略异常和错误,将它们丢弃并假装没有发生过。 - Peter Lawrey

2

来自Effective Java

如果您还没有被说服避免使用finalizers,那么这里有另一个值得考虑的小贴士:如果在finalization期间抛出未捕获的异常,则会忽略该异常,并且该对象的finalization终止[JLS,12.6]。未捕获的异常可能会使对象处于损坏状态。如果另一个线程尝试使用这样的已损坏对象,则可能会导致任意的非确定性行为。通常,未捕获的异常将终止线程并打印堆栈跟踪,但如果发生在finalizer中,则甚至不会打印警告。

问题在于当在finalize方法内部引发未捕获的异常时,对象可能会保持在损坏状态。在finalize方法中忽略未捕获的异常,但这并不意味着GC忽略了Exception,正如您的问题所暗示的那样。


2
GC本身不会调用finalize方法。相反,当GC发现一个“可终结”对象没有强引用时,它将其标记为“不可终结”,并将其移动到需要立即进行终结处理的对象队列中,并在必要时启动一个线程来处理队列中的每个项目。队列本身将充当对尚未运行终结方法的对象的强引用,当前正在运行终结操作的执行上下文将使其保持活动状态。但是一旦控制权离开终结程序,除非已在其他位置存储了强引用,否则该对象将有资格进行收集。
终结器实际上不需要做任何事情就能使GC收集对象。当对象被移到需要立即进行终结处理的对象队列中时,GC本身将清除“可终结”标记,并且从队列中取出对象以运行它的操作将消除队列作为根引用的作用。当终结器执行时,它的执行上下文将是唯一仍然保持对象活动状态的内容,因此通过任何方式离开该执行上下文(例如异常或其他方式)都将使该对象有资格进行垃圾收集。
请注意,finalize方法的真正目的不是让对象自己执行某些操作,而是允许对象通知代表它们的外部实体其服务不再需要。如果终结器没有发送此类通知而死亡,则不会发送通知。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接