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的杀死
实测第二种方式可以解决问题,但是感觉有点治标不治本,希望知道更好的方法,可以告诉博主;