Java 7 到 Java 8 的升级可能偶尔会导致在读取操作期间指示流关闭的异常。这是由于终结线程在持有流的对象上调用 Finalize() 并随后将其关闭所致。
考虑到提供的代码,由 MIMEBodyPart 扩展的 HTTPMessage 中的 Finalize() 方法会调用 close() ,该方法由 MIMEBodyPart 扩展。关闭关联的流。在执行 MIMEWriter.writePart() 期间,IOUtils.copy 从输入流中读取块直至耗尽。
在 IOUtils.copy 运行时执行 HTTPMessage.finalize() 时会出现问题,导致 Stream 关闭例外。虽然可以从堆栈帧访问 MIMEBodyPart 对象,但 JVM 会调用 Finalize()。这种行为令人困惑。
潜在解释
即使引用本地堆栈变量和活动方法调用中的对象,如果被认为“无法访问”,也可以最终确定对象并进行垃圾收集”。对于无法访问的对象,后续代码不会与其引用进行交互。
在这种特定情况下,MimeBodyPart 对象可以存储在局部变量中。由于 IOUtils.copy 中没有后续代码引用 MimeBodyPart 对象,JVM 可能会认为它无法访问,从而触发其终结。
示例和代码修改
提供了示例演示如何在活动方法调用期间最终确定对象,即使引用了堆栈。
此外,通过修改代码以在字段中而不是局部变量中保存对 FinalizeThis 对象的引用,可以观察到终结。
结论
根据最佳实践的规定,建议避免使用 Finalize()。但是,Java 8 在某些情况下有可能最终确定可访问的对象。在检查代码和排除与对象终结相关的异常时应考虑这一点。
以上是为什么强可达 Java 对象在 Java 8 中被终结?的详细内容。更多信息请关注PHP中文网其他相关文章!