ZK 6.5.2 and memory leak stopping Tomcat 7.0.32

asked 2013-06-10 09:46:52 +0800

claudioveryant gravatar image claudioveryant
9 1

Hi all,

I work with:

  • Ritchlet and ZK 6.5.2 with Comet Server Push using zkmax.jar;
  • Tomcat 7.0.32;

After runnting the attached program in a browser, I click:

  • on Stop button in Tomcat Manager;
  • on Find Leaks;

and in message field I found the follow: "The following web applications were stopped (reloaded, undeployed), but their classes from previous runs are still loaded in memory, thus causing a memory leak (use a profiler to confirm): /myapp"

My test program is IsRichletThreadServerPush. The program creates a Thread that creates a windows. After a "for" creates a Textbox and append it to the window, each time calling before "Executions.activate(dsk);" and after "Executions.deactivate(dsk);" Here the source:

import org.zkoss.zk.ui.Executions;
import org.zkoss.zk.ui.Page;
import org.zkoss.zk.ui.Desktop;
import org.zkoss.zk.ui.GenericRichlet;
import org.zkoss.zul.Textbox;
import org.zkoss.zul.Window;

public class IsRichletThreadServerPush extends GenericRichlet {
   public void service(Page p) {
      final Desktop dsk = Executions.getCurrent().getDesktop();
      final Page page = p;
      if (dsk.isServerPushEnabled() == false)
      new Thread() {
         public void run() {
            Window w = null;
            int topwin = 30;
            for (int i = 0; i < 10; i++) {
               try {
               } catch (InterruptedException e ) {
               if (w == null) { // only the first time I create the window
                  w = new Window("TestServerPush", "overlapped", true);
                  w.setStyle("position:absolute;border:solid 1px;");
                  w.setTop(new Integer(topwin)+"px");
                  topwin += 20;
               final Textbox tb = new Textbox();
               tb.setLeft(new Integer(topwin + (i * 20)).toString()+"px");
               tb.setTop(new Integer(topwin + (i * 30)).toString()+"px");
               tb.setText(new Integer(i).toString());
               try {
               } catch (Exception e ) {
            if (dsk.isServerPushEnabled() == false)

Thank in advance for all answer and happy work for all


delete flag offensive retag edit

4 Answers

Sort by ยป oldest newest most voted

answered 2013-06-11 10:09:51 +0800

avidD gravatar image avidD
166 2

Hi Claudio,

you are probably facing the PermGen error? If so, the problem is that you are starting a thread and are not stopping that thread. Running threads prevent the GarbageCollector to remove the loaded classes. When you then reload the application, the same classes are loaded again into the permanent generation. Do this a few times and tomcat will crash. In fact, it is bad practice to start your own threads. Instead, you should create a thread pool (see java.util.concurrent.Executors), e.g., like this:

      new ThreadFactoryBuilder()
        .setNameFormat(this.getClass().getSimpleName() + "-%1$d")

This should be done at some "central" place. I use a "Registry" class that is accessible via the application context. All your concurrent tasks must be handed over as "Task" instances to the thread pool which then reuses threads. This is more efficient and safer than creating your own threads.

On shutdown of the application, e.g., in a WebAppCleanupListener, you have to explicitly shut down the thread pool which ends the threads and allows the classes to be GCed.

However, PermGen errors can have many more causes (static variables, ThreadLocals not removed, jdbc drivers, etc.) which will still cause memory leaks.

One more remark, garbage collection in the permanent generation is only enabled if you start tomcat with these flags (if you are running jdk6): -XX:+UseConcMarkSweepGC -XX:+CMSClassUnloadingEnabled

Cheers, David

link publish delete flag offensive edit

answered 2013-06-12 13:34:25 +0800

claudioveryant gravatar image claudioveryant
9 1

Thanks David, unfortunately, the code of our project must to be compatible to jdk1.4.2 and the java.util.concurrent.Executors are only from jdk1.5.

Anyway I'll try what you told me.

ciao, Claudio

link publish delete flag offensive edit

answered 2013-06-21 07:15:56 +0800

avidD gravatar image avidD
166 2

Hi Claudio,

sorry for the late response, I used to get notifications from the forums, but apparently something changed.

Yes, maybe this thread thing was a bit too far off-topic. Nevertheless, you really should use the a pool, either provided by the JDK or some utility (maybe something from apache-commons?).

Back to the original problem. I assume the problem is that you never disable serverPush:

if (dsk.isServerPushEnabled() == false) // this is never true in your code

Also, you need to enable server push only once (when starting the session) and disable it once (when ending the session). This suggests a SessionListener is a good place to do so.

Cheers, David

link publish delete flag offensive edit

answered 2013-06-26 08:48:51 +0800

claudioveryant gravatar image claudioveryant
9 1

updated 2013-06-26 08:50:55 +0800

Thanks David, yes the test is wrong and I will edit and test the change. I am now engaged in the output of a new release but I will soon take up the tests on this topic.

Ciao Claudio

link publish delete flag offensive edit
Your answer
Please start posting your answer anonymously - your answer will be saved within the current session and published after you log in or create a new account. Please try to give a substantial answer, for discussions, please use comments and please do remember to vote (after you log in)!

[hide preview]

Question tools

1 follower



Asked: 2013-06-10 09:46:52 +0800

Seen: 59 times

Last updated: Jun 26 '13

Support Options
  • Email Support
  • Training
  • Consulting
  • Outsourcing
Learn More