2026/4/6 3:59:11
网站建设
项目流程
建的网站打开很慢,网站开发文档下载,阳江市招聘最新招聘,辽宁建设官方网站Finalize方法不被推荐使用原因该函数允许在子类中被重写#xff0c;用于在对象被回收时进行资源地释放。目前#xff0c;普遍的认识是#xff0c;尽量不要使用finalize()函数进行资源释放#xff0c;原因主要有以下几点:1、在finalize()时可能会导致对象复活#xff1b;2、…Finalize方法不被推荐使用原因该函数允许在子类中被重写用于在对象被回收时进行资源地释放。目前普遍的认识是尽量不要使用finalize()函数进行资源释放原因主要有以下几点:1、在finalize()时可能会导致对象复活2、finalize()函数的执行时间是没有保障的它完全由GC线程决定极端情况下若不发生GC则finalize()将没有机会执行;3、一个糟糕的 finalize()会严重影响GC的性能函数finalize()是由FinalizerThread 线程处理的。正式回收对象前这类对象会被封装为Finalizer引用对象本质是引用类型并被加入ReferenceQueue引用队列内部是链表结构由该队列调度FinalizerThread执行其finalize()方法。Finalizer内部封装了实际的回收对象如图所示。可以看到next、prev 为实现链表所需它们分别指向队列中的下一个元素和上一个元素。finalizee是要回收的对象比如在后续的示例中就为LongFinalize$LF。由于对象在回收前被Finalizer 的referent 字段进行“强引用”并加入了FinalizerThread的执行队列这意味着对象又变为可达对象因此阻止了对象的正常回收。由于在引用队列中的元素排队执行finalize()方法一旦出现性能问题将导致这些垃圾对象长时间堆积在内存中可能会导致OOM异常。-Xmx10m -Xms10m -XX:PrintGCDetails -XX:HeapDumpOnOutOfMemoryError -XX:HeapDumpPathD:/f.dump使用上述参数进行堆内存溢出的dump文件下载并使用Mat进行文件分析从最大对象中可以看到目前系统中有大量的Finalizer类这意味着FinalizerThread 执行列可能一直持有对象而来不及执行因此大量的对象堆积而无法被释放最终导致了这个OOM。去掉LF类的finalize()方法再次以相同的参数运行这段程序。可以观察到程序很快正常结束。由此|可以进一步说明finalize()对GC产生的影响。注意:一个糟糕的finalize()可能会使对象长时间被Finalizer 引用而得不到释放因此这会进一步增加GC的压力。因此finalize()应该是尽量少 地被使用。Finalizer方法重写导致OOM原因Override protected void finalize() { try { System.out.println(Thread.currentThread().getId()); Thread.sleep(1000); } catch (Exception e) { e.printStackTrace(); } }核心逻辑finalize()会让对象的 “回收流程变复杂 延迟”。finalize()是Object类的一个方法原本设计是让对象在被垃圾回收前做最后一次资源清理但它的执行机制会改变对象的 “可回收状态”。重写与不重写的区别当你不重写finalize()时1、循环里创建的LF对象是普通强引用对象循环结束后这些对象没有任何引用f是局部变量每次循环后就失效了。2、GC 可以直接识别这些 “无引用的对象”将其回收内存会被循环利用所以不会触发 OOM。重写finalize()的情况对象被 “延迟回收”最终堆积导致 OOM:当你重写finalize()后JVM 会给这类对象加一层 “特殊处理”1、包装为 Finalizer 引用每个LF对象创建后JVM 会把它包装成java.lang.ref.Finalizer对象Finalizer是一种特殊的引用类型属于 JVM 内部维护的引用2、对象暂时 “变可达”Finalizer对象会被加入 JVM 的Finalizer队列一个链表结构此时LF对象因为被Finalizer引用会从“无引用状态”变成“可达状态”——GC 认为它还有引用不能立即回收3、FinalizerThread 处理缓慢对象堆积JVM 会启动一个低优先级线程FinalizerThread负责遍历Finalizer队列、执行每个Finalizer对应的finalize()方法。但你在finalize()里加了Thread.sleep(1000)导致FinalizerThread处理每个对象要等 1 秒 —— 而你循环每秒能创建大量LF对象处理速度远赶不上创建速度最终结果大量LF对象被Finalizer持有、无法回收内存被占满触发 OOM。finalize()到底是干啥的为什么“过时”了它原本的设计是 “让对象在回收前做资源清理”但因为1、执行依赖低优先级的FinalizerThread可能迟迟不执行2、会延迟对象回收甚至会导致 OOM3、执行结果不可控所以finalize()已经被 JDK 标记为过时方法Deprecated现在完全不推荐使用。