fabric | finalize timed out 等的异常问题记录

本文深入探讨Fabric检测中遇到的异常Daemons问题,包括ReferenceQueueDaemon、FinalizerDaemon、FinalizerWatchdogDaemon和HeapTaskDaemon的工作原理及解决策略。特别关注FinalizerWatchdogDaemon可能导致的VM终止情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Fabric 检测的异常 Daemons

大佬链接 从Daemons到finalize timed out after 10 seconds
详情请查看作者链接;

形如此类问题:
在这里插入图片描述

/**
 * Calls Object.finalize() on objects in the finalizer reference queue. The VM
 * will abort if any finalize() call takes more than the maximum finalize time
 * to complete.
 *
 * @hide
 */
public final class Daemons {

    private static final int NANOS_PER_MILLI = 1000 * 1000;
    private static final int NANOS_PER_SECOND = NANOS_PER_MILLI * 1000;
    private static final long MAX_FINALIZE_NANOS = 10L * NANOS_PER_SECOND;

    public static void start() {
        ReferenceQueueDaemon.INSTANCE.start();
        FinalizerDaemon.INSTANCE.start();
        FinalizerWatchdogDaemon.INSTANCE.start();
        HeapTaskDaemon.INSTANCE.start();
    }

    public static void stop() {
        HeapTaskDaemon.INSTANCE.stop();
        ReferenceQueueDaemon.INSTANCE.stop();
        FinalizerDaemon.INSTANCE.stop();
        FinalizerWatchdogDaemon.INSTANCE.stop();
    }
    
    ...
}
  • ReferenceQueueDaemon

    • 引用队列守护线程。我们知道,在创建引用对象的时候,可以关联一个队列。当被引用对象引用的对象被GC回收的时候,被引用对象就会被加入到其创建时关联的队列去。这个加入队列的操作就是由ReferenceQueueDaemon守护线程来完成的。这样应用程序就可以知道哪些被引用的对象已经被回收了。
  • FinalizerDaemon

    • 析构守护线程。对于重写了成员函数finalize的对象,它们被GC决定回收时,并没有马上被回收,而是被放入到一个队列中,等待FinalizerDaemon守护线程去调用它们的成员函数finalize,然后再被回收。
  • FinalizerWatchdogDaemon

    • 析构监护守护线程。用来监控FinalizerDaemon线程的执行。一旦检测那些重写了finalize的对象在执行成员函数finalize时超出一定时间,那么就会退出VM。
    • 主要做的工作:
      • take starting_timestamp, //获取开始时间戳;
      • remove object for list of objects to release,// 移除对象从要release的对象列表中;
      • release object - finalize() and call native destroy() if required, //release 对象,调用finalize()方法和有需要的话也调用destroy()方法;
      • take end_timestamp, //获取结束时间戳;
      • calculate (end_timestamp - starting_timestamp) and compare against a hard coded timeout value of 10 seconds, //计算间隔时间和固定的时间相比较;
      • if timeout has reached - throw the concurrent.TimeoutException
        and kill the process. //如果时间超时,抛出TimeoutException异常且杀死进程(System.exit(2))
  • HeapTaskDaemon :

    • 堆裁剪守护线程。用来执行裁剪堆的操作,也就是用来将那些空闲的堆内存归还给系统。

主要是 FinalizerWatchdogDaemon 进程,会终结Vm;导致 finalize() timed out after XX seconds.

 /**
     * The watchdog exits the VM if the finalizer ever gets stuck. We consider
     * the finalizer to be stuck if it spends more than MAX_FINALIZATION_MILLIS
     * on one instance.
     */
    private static class FinalizerWatchdogDaemon extends Daemon {
        private static final FinalizerWatchdogDaemon INSTANCE = new FinalizerWatchdogDaemon();

        FinalizerWatchdogDaemon() {
            super("FinalizerWatchdogDaemon");
        }

        @Override public void run() {
        ...
        }
}

解决方案 参考以下几种方式:

简述: 更改联网方式

反射关闭FinalizerWatchdogDaemon对Vm的杀死

实测第二种方式可以解决问题,但是感觉有点治标不治本,希望知道更好的方法,可以告诉博主;

stackoverflow 比较有用的一篇翻译

还有这篇分析的比较全面,滴滴方案

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值