Out of Memory - TimerTask.cancel and GC


Out of Memory Defect - TimerTask.cancel and GC

TimerTask.cancel() simply marks the task as cancelled, doesn’t cause it to be garbage collected. The Timer only releases TimerTask objects when they reach the head of the queue.
In fact, the TimerTask Object is actually only removed from the queue when the TimerTask is already cancelled at the point of time when the TimerTask is being checked by the Timer. See code extracted from Timer class
java.util.TimerThread.mainLoop()
while (true) {
    if (task.state == TimerTask.CANCELLED) {
        queue.removeMin();
        continue// No action required, poll queue again
    }
                     
It is possible to fill memory with cancelled timeouts if the timeouts are sufficiently long and there are valid timeouts ahead of them in the queue.

So when we cancel TimerTask, we should also free all references hold by the TimerTask when it is cancelled, otherwise the objects in the already cancelled TimerTask still use memory and may finally cause OOM.

This problem can be verified by the following simple test program.
import java.util.*;

class Chatter extends TimerTask {
    private int[] randomA, randomB, randomC;
    public Chatter(int[] randomA, int[] randomB, int[] randomC) {
       this.randomA = randomA;
       this.randomB = randomB;
       this.randomC = randomC;
    }
    public void run() {
       System.out.println("Timer run.");
    }
    @Override
    public boolean cancel() {
       System.out.println("Timer is cancelled");
       // we should overwrite TimerTask.cancel method, and null out all references
//     randomA = null;
//     randomB = null;
//     randomC = null;
       return super.cancel();
    }
}

public class TryThread {
    public static void main(String[] argv) throws InterruptedException {
       Timer t = new Timer(false);
       long timeout = 6000000; //6000 seconds
       Chatter chatter;
       int size = 100000;
       while (true) {
           int[] randomA = new int[size], randomB = new int[size] , randomC = new int[size];
           chatter = new Chatter(randomA, randomB, randomC);
           t.schedule(chatter, timeout);
           // after 10 seconds, cancel the timerTask
           Thread.sleep(10000);
           chatter.cancel();
            System.out.println(new Date() + " before GC call, free mem: " + Runtime.getRuntime().freeMemory());
            System.gc();
            System.out.println(new Date() +  " after GC call, free mem: " + Runtime.getRuntime().freeMemory());
       }
    }
}

At first, when TimerTask is cancelled, the program doesn't null out all TimerTask's references.

Run 'java -Xmx50m TryThread', After about 7 mins, the program hits OOM.
Timer is cancelled
Tue Apr 06 22:17:17 CST 2010 before GC call, free mem: 6173440
Tue Apr 06 22:17:17 CST 2010 after GC call, free mem: 6412104
...
Timer is cancelled
Tue Apr 06 22:23:58 CST 2010 before GC call, free mem: 1153672
Tue Apr 06 22:23:58 CST 2010 after GC call, free mem: 1184120
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
        at TryThread.main(TryThread.java:30)

After add the logic to null out all references in TimerTask.cancel method, the program runs smoothly, the free memory is stable.
Timer is cancelled
Tue Apr 06 22:18:18 CST 2010 before GC call, free mem: 6173416
Tue Apr 06 22:18:18 CST 2010 after GC call, free mem: 6349088

Timer is cancelled
Wed Apr 07 00:20:38 CST 2010 before GC call, free mem: 5275920
Wed Apr 07 00:20:38 CST 2010 after GC call, free mem: 6475912

Resources:
http://forums.sun.com/thread.jspa?threadID=239011

Labels

adsense (5) Algorithm (69) Algorithm Series (35) Android (7) ANT (6) bat (8) Big Data (7) Blogger (14) Bugs (6) Cache (5) Chrome (19) Code Example (29) Code Quality (7) Coding Skills (5) Database (7) Debug (16) Design (5) Dev Tips (63) Eclipse (32) Git (5) Google (33) Guava (7) How to (9) Http Client (8) IDE (7) Interview (88) J2EE (13) J2SE (49) Java (186) JavaScript (27) JSON (7) Learning code (9) Lesson Learned (6) Linux (26) Lucene-Solr (112) Mac (10) Maven (8) Network (9) Nutch2 (18) Performance (9) PowerShell (11) Problem Solving (11) Programmer Skills (6) regex (5) Scala (6) Security (9) Soft Skills (38) Spring (22) System Design (11) Testing (7) Text Mining (14) Tips (17) Tools (24) Troubleshooting (29) UIMA (9) Web Development (19) Windows (21) xml (5)