9

We having multiple MemoryLeaks (found in the catalina.out), while reloading the context.

To clean up these threads, I created an implementation of ServletContextListener.

The contextInitialized() method is successfully called when a context is created, because I can see the log entries.

But the contextDestroyed() method is not called so my cleanup code is not invoked. Any ideas why this is happening?

Should I implement another Interface to be noticed when a context needs to be reloaded?

public class MyContextListener implements ServletContextListener {

    private static final Logger log = Logger.getLogger(MyContextListener.class);

    @Override
    public void contextDestroyed(final ServletContextEvent arg0) {
        MyContextListener.log.info("destroying Servlet Context");
        //Do stuff
        MyContextListener.log.info("Servlet Context destroyed");
    }

    @Override
    public void contextInitialized(final ServletContextEvent arg0) {
        try {
            MyContextListener.log.info("Creating Servlet Context");
            //Do stuff
        } finally {
            MyContextListener.log.info("Servlet Context created");
        }
    }
}
lucasvw
  • 1,345
  • 17
  • 36
Mirko
  • 1,512
  • 1
  • 12
  • 19
  • Tomcat calls the javax.servlet.ServletContextListener.contextDestroyed() when a web application is stopped (if it didn't that would be a serious bug). What evidence do you have that it isn't being called? – Mark Thomas May 02 '12 at 08:36
  • Only the Logfiles and the resulting MemoryLeaks-warnings. Please take a look at the implementation. – Mirko May 02 '12 at 08:51
  • Then something in your code is broken since Tomcat always calls the contextDestroyed() methods of registered ServletContextListeners when a web application is stopped. Time to post the code for your ServletContextListener and the associated log extracts. – Mark Thomas May 02 '12 at 08:56
  • Please check this [thread](http://stackoverflow.com/questions/9930773/java-webapp-memory-leak-when-using-scheduledexecutorservice/9938271#9938271) – Bruno Grieder May 02 '12 at 10:41
  • So far so good. I created a context.xml and set the context to reloadable="false", to ship successfully around the problem. So I think, that I have to implement an LifecycleListener. In the docs I read, that the LifecycleListener must placed in the tomcat/libs to be executed. Thats very bad I think, isnt it? – Mirko May 03 '12 at 07:54
  • More than 10 years after starting this question, I remember, that the root cause is that the logger is closed before the context is destroyed. Mikhail Ionkin's solution is right. – Mirko Apr 20 '23 at 08:04

2 Answers2

1

I had have the some problem, and I "fixed" it by System.out.println.

  @WebListener
  public class App implements ServletContextListener {
      private static final Logger logger = LoggerFactory.getLogger(App.class);
   
      @Override
      public void contextInitialized(ServletContextEvent sce) {
          System.out.println("START");
          logger.info("START");
      }
   
      @Override
      public void contextDestroyed(ServletContextEvent sce) {
          System.out.println("STOP");
          logger.info("STOP");
      }
  }

log.txt:

[%thread] %-5level %logger{0}:%L - %msg%n
[localhost-startStop-1] INFO  App:16 - START

stdout:

Commons Daemon procrun stdout initialized
START
STOP

It's mean that contextDestroyed has been called, but the logger was stopped before. I used org.slf4j.Logger

To manage the logging live cicle (and so to fix the problem), see: Logging from servlet context destroyed event

Mikhail Ionkin
  • 568
  • 4
  • 20
0

As far as I can see, there are a couple of issues:

  1. The servlets and filters are destroyed completely before contextDestroyed is called, so it might be too late for some tasks. I have no idea why Tomcat would report a potential memory leak before calling this method though. :-/
  2. The class loader seems to have been disabled before this method is called (potentially also true for the destroy method on filters and servlets?) meaning that if your contextDestroyed method needs any classes that haven't already been loaded, it will fail. :-(
mjaggard
  • 2,389
  • 1
  • 23
  • 45