Memory leak on reloading webapp

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

Memory leak on reloading webapp

David Pérez-2
Hi all,

This is my 1st message to the Jetty mailing lists, and don't know if this list is the most appropiate or maybe jetty-support@....

I have tried to manually reload my webapp, with simple code.  My webapp also uses the same commons-logging and log4j as Jetty.
When I remove my webapp, I used to have a memory leak due to commons-logging.  Finally I have solved this (by switching to commons-logging 1.0.4 and calling LogFactory.release()), but I see still some old classes retained in memory.  With the help of a memory profiler (JProfiler) I discovered that the culprits are static fields from Log4J and some classes from my webapp.

Is this normal?
Does this happen to anybody else?
Has anyone tried any solution?

Here is a snippet of the code I use for reloading my webapp:

    Thread hiloR = new Thread(new Runnable() {
        public void run() {
            try {
                HttpContext[] ctxs = serv.getContexts();
                for (int i = 0; i < ctxs.length; i++) {
                    if (ctxs[i] instanceof WebApplicationContext) {
                        serv.removeContext(ctxs[i]);
                        // Avoid log commons holding references to the webapp class loading
                        LogFactory.release(ctxs[i].getClassLoader());
                    }
                }
                endThreads();
                WebApplicationContext ctx = new WebApplicationContext(rutaAplWeb.toString());
                ctx.setContextPath("/");
                serv.addContext(ctx);
                ctx.start();
            } catch (Throwable e) {
                log.fatal("Ha fallado reinicio servidor", e);
            }
        }                       
    }, "Restart");
    hiloR.setDaemon(false);
    hiloR.start();

Here is the code for ending the threads:

    void endThreads() {
        Thread[] hilos = new Thread[Thread.activeCount()];
        int numHilos = Thread.enumerate(hilos);
        ArrayList hilosParados = new ArrayList();
        for (int i = 0; i < numHilos; i++) {
            Thread h = hilos[i];
            ClassLoader cl = h.getContextClassLoader();
            if (h.isAlive() && cl != null && "org.mortbay.http.ContextLoader".equals(cl.getClass().getName()) && h != Thread.currentThread()) {
                if (log.isInfoEnabled()) {
                    log.info("Dado orden parar a hilo "+h.getName());
                }
                h.interrupt();
                hilosParados.add(h);
            }
        }
        for (Iterator it = hilosParados.iterator(); it.hasNext();) {
            Thread h = (Thread) it.next();
            try {
                if (log.isDebugEnabled()) {
                    log.debug("Esperando a q pare hilo "+h.getName());
                }
                h.join(5000);
            } catch (InterruptedException e) {
                log.warn("InterruptedException para "+h.getName());
            }
        }
    }

I have made sure that my webapp isn't running any timers or extra threads.


Thanks for any possible hint.

    David
Reply | Threaded
Open this post in threaded view
|

Re: Memory leak on reloading webapp

Greg Wilkins-5

David,

what classes from your webapp are being left in memory?
Is it possible for you to identify the references that are holding them in memory?

Also what version of Jetty are you using?



David Pérez wrote:

> Hi all,
>
> This is my 1st message to the Jetty mailing lists, and don't know if
> this list is the most appropiate or maybe
> [hidden email]
> <http://lists.sourceforge.net/lists/listinfo/jetty-support>.
>
> I have tried to manually reload my webapp, with simple code.  My webapp
> also uses the same commons-logging and log4j as Jetty.
> When I remove my webapp, I used to have a memory leak due to
> commons-logging.  Finally I have solved this (by switching to
> commons-logging 1.0.4 and calling LogFactory.release()), but I see still
> some old classes retained in memory.  With the help of a memory profiler
> (JProfiler) I discovered that the culprits are static fields from Log4J
> and some classes from my webapp.
>
> Is this normal?
> Does this happen to anybody else?
> Has anyone tried any solution?
>
> Here is a snippet of the code I use for reloading my webapp:
>
>     Thread hiloR = new Thread(new Runnable() {
>         public void run() {
>             try {
>                 HttpContext[] ctxs = serv.getContexts();
>                 for (int i = 0; i < ctxs.length; i++) {
>                     if (ctxs[i] instanceof WebApplicationContext) {
>                         serv.removeContext(ctxs[i]);
>                         // Avoid log commons holding references to the
> webapp class loading
>                         *LogFactory.release(ctxs[i].getClassLoader());*
>                     }
>                 }
>                 endThreads();
>                 WebApplicationContext ctx = new
> WebApplicationContext(rutaAplWeb.toString());
>                 ctx.setContextPath("/");
>                 serv.addContext(ctx);
>                 ctx.start();
>             } catch (Throwable e) {
>                 log.fatal("Ha fallado reinicio servidor", e);
>             }
>         }                      
>     }, "Restart");
>     hiloR.setDaemon(false);
>     hiloR.start();
>
> Here is the code for ending the threads:
>
>     void endThreads() {
>         Thread[] hilos = new Thread[Thread.activeCount()];
>         int numHilos = Thread.enumerate(hilos);
>         ArrayList hilosParados = new ArrayList();
>         for (int i = 0; i < numHilos; i++) {
>             Thread h = hilos[i];
>             ClassLoader cl = h.getContextClassLoader();
>             if (h.isAlive() && cl != null &&
> "org.mortbay.http.ContextLoader".equals(cl.getClass().getName()) && h !=
> Thread.currentThread()) {
>                 if (log.isInfoEnabled()) {
>                     log.info("Dado orden parar a hilo "+h.getName());
>                 }
>                 h.interrupt();
>                 hilosParados.add(h);
>             }
>         }
>         for (Iterator it = hilosParados.iterator(); it.hasNext();) {
>             Thread h = (Thread) it.next();
>             try {
>                 if (log.isDebugEnabled()) {
>                     log.debug("Esperando a q pare hilo "+h.getName());
>                 }
>                 h.join(5000);
>             } catch (InterruptedException e) {
>                 log.warn("InterruptedException para "+h.getName());
>             }
>         }
>     }
>
> I have made sure that my webapp isn't running any timers or extra threads.
>
>
> Thanks for any possible hint.
>
>     David



-------------------------------------------------------
This SF.Net email is sponsored by Yahoo.
Introducing Yahoo! Search Developer Network - Create apps using Yahoo!
Search APIs Find out how you can build Yahoo! directly into your own
Applications - visit http://developer.yahoo.net/?fr=offad-ysdn-ostg-q22005
_______________________________________________
jetty-discuss mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/jetty-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Re: Memory leak on reloading webapp

dperez
Greg

Thanks for your interest.
Sorry for replying so late, I've been on holiday.
See my answers below.

Greg Wilkins schrieb:
David,

what classes from your webapp are being left in memory?
  
I think, nearly all of them
Is it possible for you to identify the references that are holding them in memory?
  
Basically Log4j (shared by Jetty and my webapp, accessed through Commons Loggings and Avalon LogKit) and static instances for Singleton classes in my webapp.
Also what version of Jetty are you using?

  
A very recent one: 5.1.2

David Pérez wrote:
  
Hi all,

This is my 1st message to the Jetty mailing lists, and don't know if
this list is the most appropiate or maybe
[hidden email]
<http://lists.sourceforge.net/lists/listinfo/jetty-support>.

I have tried to manually reload my webapp, with simple code.  My webapp
also uses the same commons-logging and log4j as Jetty.
When I remove my webapp, I used to have a memory leak due to
commons-logging.  Finally I have solved this (by switching to
commons-logging 1.0.4 and calling LogFactory.release()), but I see still
some old classes retained in memory.  With the help of a memory profiler
(JProfiler) I discovered that the culprits are static fields from Log4J
and some classes from my webapp.

Is this normal?
Does this happen to anybody else?
Has anyone tried any solution?

Here is a snippet of the code I use for reloading my webapp:

    Thread hiloR = new Thread(new Runnable() {
        public void run() {
            try {
                HttpContext[] ctxs = serv.getContexts();
                for (int i = 0; i < ctxs.length; i++) {
                    if (ctxs[i] instanceof WebApplicationContext) {
                        serv.removeContext(ctxs[i]);
                        // Avoid log commons holding references to the
webapp class loading
                        *LogFactory.release(ctxs[i].getClassLoader());*
                    }
                }
                endThreads();
                WebApplicationContext ctx = new
WebApplicationContext(rutaAplWeb.toString());
                ctx.setContextPath("/");
                serv.addContext(ctx);
                ctx.start();
            } catch (Throwable e) {
                log.fatal("Ha fallado reinicio servidor", e);
            }
        }                       
    }, "Restart");
    hiloR.setDaemon(false);
    hiloR.start();

Here is the code for ending the threads:

    void endThreads() {
        Thread[] hilos = new Thread[Thread.activeCount()];
        int numHilos = Thread.enumerate(hilos);
        ArrayList hilosParados = new ArrayList();
        for (int i = 0; i < numHilos; i++) {
            Thread h = hilos[i];
            ClassLoader cl = h.getContextClassLoader();
            if (h.isAlive() && cl != null &&
"org.mortbay.http.ContextLoader".equals(cl.getClass().getName()) && h !=
Thread.currentThread()) {
                if (log.isInfoEnabled()) {
                    log.info("Dado orden parar a hilo "+h.getName());
                }
                h.interrupt();
                hilosParados.add(h);
            }
        }
        for (Iterator it = hilosParados.iterator(); it.hasNext();) {
            Thread h = (Thread) it.next();
            try {
                if (log.isDebugEnabled()) {
                    log.debug("Esperando a q pare hilo "+h.getName());
                }
                h.join(5000);
            } catch (InterruptedException e) {
                log.warn("InterruptedException para "+h.getName());
            }
        }
    }

I have made sure that my webapp isn't running any timers or extra threads.


Thanks for any possible hint.

    David