2015-11-27 45 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