-
FEATURED COMPONENTS
First time here? Check out the FAQ!
Hi all,
I work with:
After runnting the attached program in a browser, I click:
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) dsk.enableServerPush(true); new Thread() { public void run() { Window w = null; int topwin = 30; for (int i = 0; i < 10; i++) { try { Executions.activate(dsk); } catch (InterruptedException e ) { } if (w == null) { // only the first time I create the window w = new Window("TestServerPush", "overlapped", true); w.setHeight("600px"); w.setWidth("600px"); w.setStyle("position:absolute;border:solid 1px;"); w.setTop(new Integer(topwin)+"px"); w.setLeft("50px"); w.setPage(page); topwin += 20; } final Textbox tb = new Textbox(); tb.setStyle("position:absolute;"); tb.setLeft(new Integer(topwin + (i * 20)).toString()+"px"); tb.setTop(new Integer(topwin + (i * 30)).toString()+"px"); tb.setText(new Integer(i).toString()); tb.setParent(w); try { Executions.deactivate(dsk); } catch (Exception e ) { } } if (dsk.isServerPushEnabled() == false) dsk.enableServerPush(false); } }.start(); } }
Thank in advance for all answer and happy work for all
Claudio
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
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
dsk.enableServerPush(false);
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
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
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:
Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors(),
new ThreadFactoryBuilder()
.setThreadFactory(Executors.defaultThreadFactory())
.setNameFormat(this.getClass().getSimpleName() + "-%1$d")
.build());
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
Asked: 2013-06-10 09:46:52 +0800
Seen: 59 times
Last updated: Jun 26 '13
ZK Clustering, Session Replication Question [closed]
ZK Tomcat 7 Cluster/Session Replication
how to deploy zk application with tomcat startup
Call to zkcomet failing the first time
ZK on tomcat7 not working when accessing by IP
how do I map my domain name to an ZK application in TOMCAT server ...