2015-11-27 60 views
2

我有一个java.util.Timer,并且我正在调度TimerTasks,它在凌晨3:00:00每24小时运行一次,但是在5-8天后Timer被GC并且我的所有任务都被取消,因为定时器实例不再存在。GC正在使用Java长时间运行的计时器

我该如何预防?

我用:

t.schedule(timerTask, date); 

然后将任务重新开始自己(在执行任务也是调用时间表再次这项任务方法)

计时器这样的定义:

public static Timer t = new java.util.Timer(); 
+0

只有当GC没有可达的引用时,计时器才会被使用。除了初始化之外,你是否随时为't'赋值? – RealSkeptic

回答

1

static变量是class的一部分,在这些变量中定义了它们,并在加载类时进行初始化。 GC可能会在某个时刻决定(特别是在内存不足且需要更多操作的情况下)卸载不再需要的类。这是你在这里可能发生的事情。您可以尝试创建Timer对象作为类的非静态成员,该类保证有一个仍由GC引用的实例。

+0

嗯,是的,但是一个类只有在无法访问时才会被卸载。这就是“不再需要”的真正含义。有些如果(可达)类中的某些代码可以使用该静态,那么包含该静态的类将是可访问的。 –

6

如果定时器声明,这样创建的:

public static Timer t = new java.util.Timer(); 

那么我认为只有两种情形可以被垃圾收集在Timer

  1. 某处在您的应用程序,东西正在给t分配一个新值,导致以前的值无法访问。

  2. 包含t声明的类已变得无法访问并且已被卸载。

第一种方案是目前最有可能的,并有一个简单的方法来避免它。声明改成这样:

public static final Timer t = new java.util.Timer(); 

第二种方案是唯一可行的,如果你的应用程序(或者,它使用的是框架)加载动态类使用本身成为一个不可达的类加载器。

+0

我100%确定没有任何东西会给定时器赋予新值。 – Welite

+0

即便如此,将声明更改为“final”,以便编译器知道不应该为其分配任何内容。如果改变后仍然存在问题,那么你知道问题是其他问题。 –

+0

我已经创建了新的Timer类,它基本上是一个扩展java.util.Timer的类,但是我添加了public void finalize()...方法,所以我知道垃圾收集器何时吃晚餐的定时器。 – Welite