由于耗时的 finalize() 方法导致的内存泄漏

主要观点:Java 中所有对象隐式继承自java.lang.Objectfinalize()方法可在子类中重写用于关闭类中打开的资源,但此方法有缺点,已在 Java 9 中被弃用,应避免使用。
关键信息

  • 未妥善处理的finalize()方法会导致OutOfMemoryError,如示例程序中不断创建SlowFinalizerObjectfinalize()方法执行时间长,会使Finalizer线程卡住,内部队列堆积,超出内存分配大小时抛出错误。
  • 诊断finalize()方法创建的内存泄漏需捕获堆转储(如通过-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=<FILE_PATH_LOCATION>)并使用工具分析,如 HeapHero 可利用机器学习算法检测内存泄漏模式。
  • 替代finalize()方法的策略有使用try-with-resourcesjava.lang.ref.Cleanerjava.lang.ref.PhantomReference、设计显式清理方法等。
    重要细节
  • 示例程序中SlowFinalizerObject在创建时会生成巨大字符串并在finalize()方法中模拟长时间执行,导致OutOfMemoryError,移除finalize()方法则程序可正常运行。
  • HeapHero 工具可分析堆转储,通过“Largest Objects”和“Outgoing Reference”等部分指出java.lang.ref.Finalizer类占用大量内存及内存泄漏对象及其来源。
  • 替代finalize()方法的策略各有特点,try-with-resources可保证资源及时清理,Cleaner更安全,PhantomReference可监控对象收集,显式清理方法让开发者可控资源管理。
阅读 11
0 条评论