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
Post a Comment

Labels

Java (159) Lucene-Solr (112) Interview (61) All (58) J2SE (53) Algorithm (45) Soft Skills (38) Eclipse (33) Code Example (31) Linux (25) JavaScript (23) Spring (22) Windows (22) Web Development (20) Tools (19) Nutch2 (18) Bugs (17) Debug (16) Defects (14) Text Mining (14) J2EE (13) Network (13) Troubleshooting (13) PowerShell (11) Chrome (9) Design (9) How to (9) Learning code (9) Performance (9) Problem Solving (9) UIMA (9) html (9) Http Client (8) Maven (8) Security (8) bat (8) blogger (8) Big Data (7) Continuous Integration (7) Google (7) Guava (7) JSON (7) Shell (7) ANT (6) Coding Skills (6) Database (6) Lesson Learned (6) Programmer Skills (6) Scala (6) Tips (6) css (6) Algorithm Series (5) Cache (5) Dynamic Languages (5) IDE (5) System Design (5) adsense (5) xml (5) AIX (4) Code Quality (4) GAE (4) Git (4) Good Programming Practices (4) Jackson (4) Memory Usage (4) Miscs (4) OpenNLP (4) Project Managment (4) Spark (4) Testing (4) ads (4) regular-expression (4) Android (3) Apache Spark (3) Become a Better You (3) Concurrency (3) Eclipse RCP (3) English (3) Happy Hacking (3) IBM (3) J2SE Knowledge Series (3) JAX-RS (3) Jetty (3) Restful Web Service (3) Script (3) regex (3) seo (3) .Net (2) Android Studio (2) Apache (2) Apache Procrun (2) Architecture (2) Batch (2) Bit Operation (2) Build (2) Building Scalable Web Sites (2) C# (2) C/C++ (2) CSV (2) Career (2) Cassandra (2) Distributed (2) Fiddler (2) Firefox (2) Google Drive (2) Gson (2) How to Interview (2) Html Parser (2) Http (2) Image Tools (2) JQuery (2) Jersey (2) LDAP (2) Life (2) Logging (2) Python (2) Software Issues (2) Storage (2) Text Search (2) xml parser (2) AOP (1) Application Design (1) AspectJ (1) Chrome DevTools (1) Cloud (1) Codility (1) Data Mining (1) Data Structure (1) ExceptionUtils (1) Exif (1) Feature Request (1) FindBugs (1) Greasemonkey (1) HTML5 (1) Httpd (1) I18N (1) IBM Java Thread Dump Analyzer (1) JDK Source Code (1) JDK8 (1) JMX (1) Lazy Developer (1) Mac (1) Machine Learning (1) Mobile (1) My Plan for 2010 (1) Netbeans (1) Notes (1) Operating System (1) Perl (1) Problems (1) Product Architecture (1) Programming Life (1) Quality (1) Redhat (1) Redis (1) Review (1) RxJava (1) Solutions logs (1) Team Management (1) Thread Dump Analyzer (1) Visualization (1) boilerpipe (1) htm (1) ongoing (1) procrun (1) rss (1)

Popular Posts