You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tomcat.apache.org by Martin O'Shea <ap...@dsl.pipex.com> on 2010/10/16 13:44:49 UTC

Tomcat memory leak error launching web app in NetBeans 6.9.1

Hello 

I wonder if anyone can help here? I am developing a web application written
in Java servlets and JSPs which uses Quartz 1.6.1 to submit two jobs when
Apache Tomcat 6.0.26 is started and hourly after that. 

But what I'm finding is that a message is issued several times as the server
is started in NetBeans 6.9.1. The message is: 

16-Oct-2010 12:20:18 org.apache.catalina.loader.WebappClassLoader
clearReferencesThreads 
SEVERE: A web application appears to have started a thread named
[DefaultQuartzScheduler_Worker-1] but has failed to stop it. This is very
likely to create a memory leak. 

Has anyone any idea? It seems to be causing Tomcat to stop every so often
requiring a PC reboot. And I've found very little about this so far. 

I don't know if it is a problem with Tomcat or Quartz so any help is welcome


Thanks 

Martin O'Shea. 




RE: Tomcat memory leak error launching web app in NetBeans 6.9.1

Posted by "Caldarale, Charles R" <Ch...@unisys.com>.
> From: Martin O'Shea [mailto:appy74@dsl.pipex.com] 
> Subject: Tomcat memory leak error launching web app in NetBeans 6.9.1

> 16-Oct-2010 12:20:18 org.apache.catalina.loader.WebappClassLoader
> clearReferencesThreads 
> SEVERE: A web application appears to have started a thread named
> [DefaultQuartzScheduler_Worker-1] but has failed to stop it. This is very
> likely to create a memory leak. 

The above message is displayed when a webapp is *stopped*, not started (including Tomcat shutdown).

> I don't know if it is a problem with Tomcat or Quartz 
> so any help is welcome

Neither - it's an error in your webapp due to its failure to manage resources that it is using.  If your webapp starts a thread, your webapp must be prepared to stop the thread during shutdown.  This is usually accomplished by configuring and implementing a ServletContextListener in your webapp.

 - Chuck


THIS COMMUNICATION MAY CONTAIN CONFIDENTIAL AND/OR OTHERWISE PROPRIETARY MATERIAL and is thus for use only by the intended recipient. If you received this in error, please contact the sender and delete the e-mail and its attachments from all computers.


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


RE: Tomcat memory leak error launching web app in NetBeans 6.9.1

Posted by Martin O'Shea <ap...@dsl.pipex.com>.
This answers a few questions. I thought also that I had the most recent version of Quartz running but I only have version 1.6.1. They are up to 1.8.3 so I will try this out.

Thanks.

-----Original Message-----
From: Pid [mailto:pid@pidster.com] 
Sent: 16 Oct 2010 17 33
To: Tomcat Users List
Subject: Re: Tomcat memory leak error launching web app in NetBeans 6.9.1

On 16/10/2010 15:24, Martin O'Shea wrote:
> OK. So the error is happening as the application is closed, not as it started. My mistake. But Tomcat restarts occur frequently as I have NetBeans's Deploy on Save set. This seems to restart the server with the current objects.
> 
> But what I don't understand is why the ServletContextListener which handles Quartz jobs should be going wrong? It is set to start and stop Quartz at contextInitialized and contextDestroyed times where the former creates an instance of a SchedulerController class which submits the two jobs. 

Is the Quartz lib the latest version?

> This problem never appeared to happen under NetBeans 6.9 with an earlier version of Tomcat which I was using recently. 

The memory leak detection was released in 6.0.24.  So the problem might have existed, you just might not have known about it.

> And I wonder if this may have anything to do with the Tomcat out of memory messages I've been receiving? Do I need to increase the memory allocated to the JVM for Tomcat at all?

Some of the detection just results in a log message, some of it results in a message and an attempt to clean up.


p

> -----Original Message-----
> From: Pid * [mailto:pid@pidster.com]
> Sent: 16 Oct 2010 15 06
> To: Tomcat Users List
> Subject: Re: Tomcat memory leak error launching web app in NetBeans 
> 6.9.1
> 
> On 16 Oct 2010, at 12:45, Martin O'Shea <ap...@dsl.pipex.com> wrote:
> 
>> Hello
>>
>> I wonder if anyone can help here? I am developing a web application 
>> written in Java servlets and JSPs which uses Quartz 1.6.1 to submit 
>> two jobs when Apache Tomcat 6.0.26 is started and hourly after that.
>>
>> But what I'm finding is that a message is issued several times as the 
>> server is started in NetBeans 6.9.1. The message is:
>>
>> 16-Oct-2010 12:20:18 org.apache.catalina.loader.WebappClassLoader
>> clearReferencesThreads
>> SEVERE: A web application appears to have started a thread named 
>> [DefaultQuartzScheduler_Worker-1] but has failed to stop it. This is 
>> very likely to create a memory leak.
> 
> Yes. So, umm, your webapp uses quartz - which is starting threads and 
> not stopping them.
> 
>> Has anyone any idea? It seems to be causing Tomcat to stop every so 
>> often requiring a PC reboot. And I've found very little about this so far.
> 
> The error message is issued by Tomcat when an app is stopped and it 
> finds resources that haven't been properly terminated.
> 
> The message itself is doesn't cause a leak, the source of the problem 
> might - as the message itself states.
> 
>> I don't know if it is a problem with Tomcat or Quartz so any help is 
>> welcome
> 
> Quartz, or the way you've configured it.
> 
> 
> p
> 
>>
>>
>> Thanks
>>
>> Martin O'Shea.
>>
>>
>>
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
> For additional commands, e-mail: users-help@tomcat.apache.org
> 
> 
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
> For additional commands, e-mail: users-help@tomcat.apache.org
> 




---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


RE: Tomcat memory leak error launching web app in NetBeans 6.9.1

Posted by Martin O'Shea <ap...@dsl.pipex.com>.
Well, I've upgraded to Quartz 1.8.3 and the two SLF4J files that seem to be needed. I believe Quartz's config is correct with regards to the two scheduled jobs I have. But upon terminating my web app in Tomcat or terminating Tomcat, I still find a number of messages:

-Oct-2010 14:40:52 org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: A web application appears to have started a thread named [DefaultQuartzScheduler_Worker-1] but has failed to stop it. This is very likely to create a memory leak.

Any clues?



---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Tomcat memory leak error launching web app in NetBeans 6.9.1

Posted by Pid <pi...@pidster.com>.
On 16/10/2010 15:24, Martin O'Shea wrote:
> OK. So the error is happening as the application is closed, not as it started. My mistake. But Tomcat restarts occur frequently as I have NetBeans's Deploy on Save set. This seems to restart the server with the current objects.
> 
> But what I don't understand is why the ServletContextListener which handles Quartz jobs should be going wrong? It is set to start and stop Quartz at contextInitialized and contextDestroyed times where the former creates an instance of a SchedulerController class which submits the two jobs. 

Is the Quartz lib the latest version?

> This problem never appeared to happen under NetBeans 6.9 with an earlier version of Tomcat which I was using recently. 

The memory leak detection was released in 6.0.24.  So the problem might
have existed, you just might not have known about it.

> And I wonder if this may have anything to do with the Tomcat out of memory messages I've been receiving? Do I need to increase the memory allocated to the JVM for Tomcat at all?

Some of the detection just results in a log message, some of it results
in a message and an attempt to clean up.


p

> -----Original Message-----
> From: Pid * [mailto:pid@pidster.com] 
> Sent: 16 Oct 2010 15 06
> To: Tomcat Users List
> Subject: Re: Tomcat memory leak error launching web app in NetBeans 6.9.1
> 
> On 16 Oct 2010, at 12:45, Martin O'Shea <ap...@dsl.pipex.com> wrote:
> 
>> Hello
>>
>> I wonder if anyone can help here? I am developing a web application written
>> in Java servlets and JSPs which uses Quartz 1.6.1 to submit two jobs when
>> Apache Tomcat 6.0.26 is started and hourly after that.
>>
>> But what I'm finding is that a message is issued several times as the server
>> is started in NetBeans 6.9.1. The message is:
>>
>> 16-Oct-2010 12:20:18 org.apache.catalina.loader.WebappClassLoader
>> clearReferencesThreads
>> SEVERE: A web application appears to have started a thread named
>> [DefaultQuartzScheduler_Worker-1] but has failed to stop it. This is very
>> likely to create a memory leak.
> 
> Yes. So, umm, your webapp uses quartz - which is starting threads and
> not stopping them.
> 
>> Has anyone any idea? It seems to be causing Tomcat to stop every so often
>> requiring a PC reboot. And I've found very little about this so far.
> 
> The error message is issued by Tomcat when an app is stopped and it
> finds resources that haven't been properly terminated.
> 
> The message itself is doesn't cause a leak, the source of the problem
> might - as the message itself states.
> 
>> I don't know if it is a problem with Tomcat or Quartz so any help is welcome
> 
> Quartz, or the way you've configured it.
> 
> 
> p
> 
>>
>>
>> Thanks
>>
>> Martin O'Shea.
>>
>>
>>
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
> For additional commands, e-mail: users-help@tomcat.apache.org
> 
> 
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
> For additional commands, e-mail: users-help@tomcat.apache.org
> 


Heading [OT] Re: Tomcat memory leak error launching web app in NetBeans 6.9.1

Posted by Pid <pi...@pidster.com>.
On 19/10/2010 01:07, Mark Eggers wrote:
> Once again, I apologize for the wall of text. However, most of it is
> pretty quick and dirty code, so it should be easy to skim.
> 
> I'm guessing the end result is harmless?

Well, if the ClassLoader is still extant after it's supposed to have
been cleared up, it isn't so harmless.

> It does seem like a race condition.
>
> Everything seems to work fine
> until shutdown. When DEBUG is set in logging, you get the following in
> catalina.out:

<snip>

> org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:595)
> 
> Here's the relevant portions of the class in question (both 
> from org.quartz.simpl.SimpleThreadPool):
> 
>     try {
>         getLog().debug("WorkerThread is shut down.");
>     } catch(Exception e) {
>         // ignore to help with a tomcat glitch
>     }

A Tomcat glitch?  Maybe we should find out what that was, given the edit
was 5 years ago...


> And part of the shutdown code - lots of hard-coded wait times:
> 
> public void shutdown(boolean waitForJobsToComplete) {
>     synchronized (nextRunnableLock) {
>         isShutdown = true;
>         if(workers == null) // case where the pool wasn't even initialize()ed
>             return;
>         // signal each worker thread to shut down
>         Iterator workerThreads = workers.iterator();
>         while(workerThreads.hasNext()) {
>             WorkerThread wt = (WorkerThread) workerThreads.next();
>             wt.shutdown();

This is where the thread is told to shutdown.

>             availWorkers.remove(wt);
>         }

>         // Give waiting (wait(1000)) worker threads a chance to shut down.

It's 1000 in the comment here ^^

>         // Active worker threads will shut down after finishing their
>         // current job.
>         nextRunnableLock.notifyAll();
>         if (waitForJobsToComplete == true) {
>             // wait for hand-off in runInThread to complete...
>             while(handoffPending) {
>                 try { nextRunnableLock.wait(100); } catch(Throwable t) {}
>             }

It's 100 here ^^

>             // Wait until all worker threads are shut down
>             while (busyWorkers.size() > 0) {
>                 WorkerThread wt = (WorkerThread) busyWorkers.getFirst();
>                 try {
>                     getLog().debug(
>                             "Waiting for thread " + wt.getName()
>                                     + " to shut down");
>                     // note: with waiting infinite time the
>                     // application may appear to 'hang'.
>                     nextRunnableLock.wait(2000);

It's 2000 here ^^

>                 } catch (InterruptedException ex) {
>                 }
>             }
>             getLog().debug("shutdown complete");
>         }
>     }
> }
> 
> Looking at the above code, there's a wait of 2.1 seconds per thread?
> If that's the case, then the 3 threads will take up to 6.3 seconds
> while waiting.

6.1s, the 100ms wait only happens once doesn't it?


> What's odd is that I don't see the entry: "Waiting for thread " name "
> to shut down" in any of the logs.

You'd need to set 'debug' on Quartz & the package the class is in, I guess.


> Here's some admittedly ugly code I put together:

<snip>


Tangent: I wonder if removing each Job from the Scheduler prior to
shutdown has a bearing on Quartz ability to find & stop them.

Tomcat's log message reports that the threads aren't actually stopped,
so does Quartz actually wait for them to stop, or does it just wait for
2secs and then move on to the next thread?

Quartz doesn't seem to be aware that the job thread is still running.


p

RE: Tomcat memory leak error launching web app in NetBeans 6.9.1

Posted by Martin O'Shea <ap...@dsl.pipex.com>.
Thanks Mark. I will give this a try later on.

-----Original Message-----
From: Mark Eggers [mailto:its_toasted@yahoo.com] 
Sent: 19 Oct 2010 01 08
To: Tomcat Users List
Subject: Re: Tomcat memory leak error launching web app in NetBeans 6.9.1

Once again, I apologize for the wall of text. However, most of it is
pretty quick and dirty code, so it should be easy to skim.

I'm guessing the end result is harmless?

It does seem like a race condition. Everything seems to work fine
until shutdown. When DEBUG is set in logging, you get the following in
catalina.out:

Oct 18, 2010 4:12:38 PM org.apache.catalina.loader.WebappClassLoader 
clearReferencesThreads
SEVERE: The web application [/QSchedule] appears to have started a
thread named [SampleScheduler_Worker-1] but has failed to stop it.
This is very likely to create a memory leak.

Oct 18, 2010 4:12:38 PM org.apache.catalina.loader.WebappClassLoader 
clearReferencesThreads
SEVERE: The web application [/QSchedule] appears to have started a
thread named [SampleScheduler_Worker-2] but has failed to stop it.
This is very likely to create a memory leak.

Oct 18, 2010 4:12:38 PM org.apache.catalina.loader.WebappClassLoader 
clearReferencesThreads
SEVERE: The web application [/QSchedule] appears to have started a
thread named [SampleScheduler_Worker-3] but has failed to stop it.
This is very likely to create a memory leak.

Oct 18, 2010 4:12:38 PM org.apache.catalina.loader.WebappClassLoader
loadClass
INFO: Illegal access: this web application instance has been stopped
already.  Could not load java.io.PrintStream.  The eventual following
stack trace is caused by an error thrown for debugging purposes as
well as to attempt to terminate the thread which caused the illegal
access, and has no functional impact.

java.lang.IllegalStateException
at 
org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.jav
a:1531)

at 
org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.jav
a:1491)

at org.apache.log4j.helpers.LogLog.error(LogLog.java:142)
at 
org.apache.log4j.helpers.PatternParser$DatePatternConverter.convert(PatternP
arser.java:447)

at
org.apache.log4j.helpers.PatternConverter.format(PatternConverter.java:64)
at org.apache.log4j.PatternLayout.format(PatternLayout.java:503)
at org.apache.log4j.WriterAppender.subAppend(WriterAppender.java:301)
at org.apache.log4j.WriterAppender.append(WriterAppender.java:159)
at org.apache.log4j.AppenderSkeleton.doAppend(AppenderSkeleton.java:230)
at 
org.apache.log4j.helpers.AppenderAttachableImpl.appendLoopOnAppenders(Append
erAttachableImpl.java:65)

at org.apache.log4j.Category.callAppenders(Category.java:203)
at org.apache.log4j.Category.forcedLog(Category.java:388)
at org.apache.log4j.Category.log(Category.java:853)
at org.slf4j.impl.Log4jLoggerAdapter.debug(Log4jLoggerAdapter.java:204)
at
org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:595
)
log4j:ERROR Error occured while converting date.
java.lang.NullPointerException
at java.lang.AbstractStringBuilder.append(Unknown Source)
at java.lang.StringBuffer.append(Unknown Source)
at
org.apache.log4j.helpers.ISO8601DateFormat.format(ISO8601DateFormat.java:132
)
at java.text.DateFormat.format(Unknown Source)
at 
org.apache.log4j.helpers.PatternParser$DatePatternConverter.convert(PatternP
arser.java:444)

at
org.apache.log4j.helpers.PatternConverter.format(PatternConverter.java:64)
at org.apache.log4j.PatternLayout.format(PatternLayout.java:503)
at org.apache.log4j.WriterAppender.subAppend(WriterAppender.java:301)
at org.apache.log4j.WriterAppender.append(WriterAppender.java:159)
at org.apache.log4j.AppenderSkeleton.doAppend(AppenderSkeleton.java:230)
at 
org.apache.log4j.helpers.AppenderAttachableImpl.appendLoopOnAppenders(Append
erAttachableImpl.java:65)

at org.apache.log4j.Category.callAppenders(Category.java:203)
at org.apache.log4j.Category.forcedLog(Category.java:388)
at org.apache.log4j.Category.log(Category.java:853)
at org.slf4j.impl.Log4jLoggerAdapter.debug(Log4jLoggerAdapter.java:204)
at
org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:595
)
log4j:ERROR Error occured while converting date.
java.lang.NullPointerException
at java.lang.AbstractStringBuilder.append(Unknown Source)
at java.lang.StringBuffer.append(Unknown Source)
at
org.apache.log4j.helpers.ISO8601DateFormat.format(ISO8601DateFormat.java:132
)
at java.text.DateFormat.format(Unknown Source)
at 
org.apache.log4j.helpers.PatternParser$DatePatternConverter.convert(PatternP
arser.java:444)

at
org.apache.log4j.helpers.PatternConverter.format(PatternConverter.java:64)
at org.apache.log4j.PatternLayout.format(PatternLayout.java:503)
at org.apache.log4j.WriterAppender.subAppend(WriterAppender.java:301)
at org.apache.log4j.WriterAppender.append(WriterAppender.java:159)
at org.apache.log4j.AppenderSkeleton.doAppend(AppenderSkeleton.java:230)
at 
org.apache.log4j.helpers.AppenderAttachableImpl.appendLoopOnAppenders(Append
erAttachableImpl.java:65)

at org.apache.log4j.Category.callAppenders(Category.java:203)
at org.apache.log4j.Category.forcedLog(Category.java:388)
at org.apache.log4j.Category.log(Category.java:853)
at org.slf4j.impl.Log4jLoggerAdapter.debug(Log4jLoggerAdapter.java:204)
at
org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:595
)
log4j:ERROR Error occured while converting date.
java.lang.NullPointerException
at java.lang.AbstractStringBuilder.append(Unknown Source)
at java.lang.StringBuffer.append(Unknown Source)
at
org.apache.log4j.helpers.ISO8601DateFormat.format(ISO8601DateFormat.java:132
)
at java.text.DateFormat.format(Unknown Source)
at 
org.apache.log4j.helpers.PatternParser$DatePatternConverter.convert(PatternP
arser.java:444)

at
org.apache.log4j.helpers.PatternConverter.format(PatternConverter.java:64)
at org.apache.log4j.PatternLayout.format(PatternLayout.java:503)
at org.apache.log4j.WriterAppender.subAppend(WriterAppender.java:301)
at org.apache.log4j.WriterAppender.append(WriterAppender.java:159)
at org.apache.log4j.AppenderSkeleton.doAppend(AppenderSkeleton.java:230)
at 
org.apache.log4j.helpers.AppenderAttachableImpl.appendLoopOnAppenders(Append
erAttachableImpl.java:65)

at org.apache.log4j.Category.callAppenders(Category.java:203)
at org.apache.log4j.Category.forcedLog(Category.java:388)
at org.apache.log4j.Category.log(Category.java:853)
at org.slf4j.impl.Log4jLoggerAdapter.debug(Log4jLoggerAdapter.java:204)
at
org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:595
)

Here's the relevant portions of the class in question (both 
from org.quartz.simpl.SimpleThreadPool):

    try {
        getLog().debug("WorkerThread is shut down.");
    } catch(Exception e) {
        // ignore to help with a tomcat glitch
    }

And part of the shutdown code - lots of hard-coded wait times:

public void shutdown(boolean waitForJobsToComplete) {
    synchronized (nextRunnableLock) {
        isShutdown = true;
        if(workers == null) // case where the pool wasn't even
initialize()ed
            return;
        // signal each worker thread to shut down
        Iterator workerThreads = workers.iterator();
        while(workerThreads.hasNext()) {
            WorkerThread wt = (WorkerThread) workerThreads.next();
            wt.shutdown();
            availWorkers.remove(wt);
        }
        // Give waiting (wait(1000)) worker threads a chance to shut down.
        // Active worker threads will shut down after finishing their
        // current job.
        nextRunnableLock.notifyAll();
        if (waitForJobsToComplete == true) {
            // wait for hand-off in runInThread to complete...
            while(handoffPending) {
                try { nextRunnableLock.wait(100); } catch(Throwable t) {}
            }
            // Wait until all worker threads are shut down
            while (busyWorkers.size() > 0) {
                WorkerThread wt = (WorkerThread) busyWorkers.getFirst();
                try {
                    getLog().debug(
                            "Waiting for thread " + wt.getName()
                                    + " to shut down");
                    // note: with waiting infinite time the
                    // application may appear to 'hang'.
                    nextRunnableLock.wait(2000);
                } catch (InterruptedException ex) {
                }
            }
            getLog().debug("shutdown complete");
        }
    }
}

Looking at the above code, there's a wait of 2.1 seconds per thread?
If that's the case, then the 3 threads will take up to 6.3 seconds
while waiting.

What's odd is that I don't see the entry: "Waiting for thread " name "
to shut down" in any of the logs.

Here's some admittedly ugly code I put together:

The listener:

package org.mdeggers.qschedule.utils;

import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.Properties;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import org.apache.log4j.Logger;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.Trigger;
import org.quartz.TriggerUtils;
import org.quartz.impl.StdSchedulerFactory;

/**
 * Web application lifecycle listener.
 * @author mdeggers
 */
public class DIYCronListener implements ServletContextListener {

    private static final Logger log =
Logger.getLogger(DIYCronListener.class);
    private SchedulerFactory schedFactory = null;
    private Scheduler scheduler = null;

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        int schedInterval = 
Integer.parseInt(sce.getServletContext().getInitParameter("quartz:schedule-i
nterval"));

        String propsFile = 
sce.getServletContext().getInitParameter("quartz:config-file");
        Properties props = new Properties();

        // loading properties file
        InputStream in = 
this.getClass().getClassLoader().getResourceAsStream(propsFile);
        try {
            props.load(in);
        } catch (IOException ex) {
            log.fatal("Failed to load properties file: ", ex);
        }
        try {
            in.close();
        } catch (IOException ex) {
            log.fatal("Failed to close properties file: ", ex);
        }

        // creating the scheduler factory
        try {
            schedFactory = new StdSchedulerFactory(props);
            log.info("Got scheduler factory with the appropriate
properties");
            // getting the scheduler
            try {
                scheduler = schedFactory.getScheduler();
                log.info("Got scheduler from schedule factory");
            } catch (SchedulerException ex) {
                log.fatal("Failed to get a scheduler: ", ex);
            }
        } catch (SchedulerException ex) {
            log.fatal("Failed to get a scheduler factory: ", ex);
        }

        // creating the job - yep, hardcoded
        String jobName = "LogJob";
        JobDetail jobDetail = new JobDetail(jobName, DumbJob.class);

        // creating the trigger
        Trigger trigger = TriggerUtils.makeSecondlyTrigger(schedInterval);
        trigger.setStartTime(new Date());
        trigger.setName(jobName);

        // now try to start the scheduler and add the job
        if (scheduler != null) {
            try {
                scheduler.start();
                log.info("Scheduler started");
                // try to add the job
                try {
                    Date jobDate = scheduler.scheduleJob(jobDetail,
trigger);
                    log.info("Job started: " + jobName + " on " + 
jobDate.toString());
                } catch (SchedulerException ex) {
                    log.fatal("Failed to add job: ", ex);
                }
            } catch (SchedulerException ex) {
                log.fatal("Failed to start scheduler", ex);
            }
        }
        log.info("I have started.");
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        boolean qWait = 
Boolean.parseBoolean(sce.getServletContext().getInitParameter("quartz:shutdo
wn-wait"));

        try {
            if (scheduler.isStarted()) {
                try {
                    scheduler.shutdown(qWait);
                    log.info("Shutting down scheduler");
                } catch (SchedulerException ex) {
                    log.fatal("Failed to shut down scheduler: ", ex);
                }
            } else {
                log.info("Scheduler returns not started");
            }
        } catch (SchedulerException ex) {
            log.fatal("Could not determine if scheduler was started", ex);
        }
    }
}

The job:

package org.mdeggers.qschedule.utils;

import org.apache.log4j.Logger;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

/**
 *
 * @author mdeggers
 */
public class DumbJob implements Job {
    private static final Logger log = Logger.getLogger(DumbJob.class);
    
    public DumbJob() {
    }

    @Override
    public void execute(JobExecutionContext context) throws 
JobExecutionException {
        log.info("Hello from the Dumb job.");
    }
}

The log4j.xml file:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration PUBLIC 'PUBLIC:-//log4j/log4j
Configuration//EN' 
'log4j.dtd'>
<log4j:configuration>
    <appender name="FA" class="org.apache.log4j.FileAppender">
        <param name="File" value="${log4j.home}/qschedule.log"/>
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%d %-5p %c.%M:%L -
%m%n"/>
        </layout>
    </appender>
    <appender name="QA" class="org.apache.log4j.FileAppender">
        <param name="File" value="${log4j.home}/quartz-debug.log"/>
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%d %-5p %c.%M:%L -
%m%n"/>
        </layout>
    </appender>
<!-- debug for quartz scheduler - trying to find out where the holdup is -->
    <logger name="org.quartz">
        <level value="DEBUG"/>
        <appender-ref ref="QA"/>
    </logger>
<!-- info from my classes -->
    <logger name="org.mdeggers">
        <level value="INFO"/>
        <appender-ref ref="FA"/>
    </logger>
</log4j:configuration>

The properties file (quartz.properties)

org.quartz.scheduler.instanceName = SampleScheduler
org.quartz.scheduler.instanceId = 1
org.quartz.scheduler.rmi.export = false
org.quartz.scheduler.rmi.proxy = false

org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 3

org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore
org.quartz.scheduler.skipUpdateCheck = true

And the corresponding parts of the web.xml file:

<context-param>
    <description>Quartz scheduler configuration file</description>
    <param-name>quartz:config-file</param-name>
    <param-value>quartz.properties</param-value>
</context-param>
<context-param>
    <description>Time in seconds between scheduler executions</description>
    <param-name>quartz:schedule-interval</param-name>
    <param-value>150</param-value>
</context-param>
<context-param>
    <description>Quartz scheduler wait to finish jobs before 
shutdown</description>
    <param-name>quartz:shutdown-wait</param-name>
    <param-value>true</param-value>
</context-param>
<listener>
     <description>Do it yourself Quartz Scheduler</description>
   
 
<listener-class>org.mdeggers.qschedule.utils.DIYCronListener</listener-class
>
</listener>

The log files generated look reasonable.

qschedule.log:

2010-10-18 16:08:01,067 INFO 
  org.mdeggers.qschedule.utils.DIYCronListener.contextInitialized:50
  - Got scheduler factory with the appropriate properties
2010-10-18 16:08:01,289 INFO
  org.mdeggers.qschedule.utils.DIYCronListener.contextInitialized:54
  - Got scheduler from schedule factory
2010-10-18 16:08:01,308 INFO
  org.mdeggers.qschedule.utils.DIYCronListener.contextInitialized:75
  - Scheduler started
2010-10-18 16:08:01,335 INFO
  org.mdeggers.qschedule.utils.DIYCronListener.contextInitialized:79
  - Job started: LogJob on Mon Oct 18 16:08:01 PDT 2010
2010-10-18 16:08:01,336 INFO
  org.mdeggers.qschedule.utils.DIYCronListener.contextInitialized:87
  - I have started.
2010-10-18 16:08:01,394 INFO
  org.mdeggers.qschedule.utils.DumbJob.execute:25
  - Hello from the Dumb job.
2010-10-18 16:10:31,309 INFO
  org.mdeggers.qschedule.utils.DumbJob.execute:25
  - Hello from the Dumb job.
2010-10-18 16:12:38,494 INFO
  org.mdeggers.qschedule.utils.DIYCronListener.contextDestroyed:97
  - Shutting down scheduler

quartz-debug.log:

2010-10-18 16:08:01,276 INFO
org.quartz.core.SchedulerSignalerImpl.<init>:60 - Initialized
Scheduler Signaller of type: class org.quartz.core.SchedulerSignalerImpl

2010-10-18 16:08:01,277 INFO
org.quartz.core.QuartzScheduler.<init>:219 - Quartz Scheduler v.1.8.3
created.

2010-10-18 16:08:01,281 INFO org.quartz.simpl.RAMJobStore.initialize:139 - 
RAMJobStore initialized.

2010-10-18 16:08:01,284 INFO
org.quartz.core.QuartzScheduler.initialize:241 - Scheduler meta-data:
Quartz Scheduler (v1.8.3) 'SampleScheduler' with instanceId '1'

  Scheduler class: 'org.quartz.core.QuartzScheduler' - running locally.
  NOT STARTED.
  Currently in standby mode.
  Number of jobs executed: 0
  Using thread pool 'org.quartz.simpl.SimpleThreadPool' - with 3 threads.
  Using job-store 'org.quartz.simpl.RAMJobStore' - which does not support 
persistence.
  and is not clustered.

2010-10-18 16:08:01,286 INFO
org.quartz.impl.StdSchedulerFactory.instantiate:1275 - Quartz
scheduler 'SampleScheduler' initialized from an externally provided
properties instance.

2010-10-18 16:08:01,288 INFO
org.quartz.impl.StdSchedulerFactory.instantiate:1279 - Quartz
scheduler version: 1.8.3

2010-10-18 16:08:01,306 INFO org.quartz.core.QuartzScheduler.start:497
- Scheduler SampleScheduler_$_1 started.

2010-10-18 16:08:01,346 DEBUG
org.quartz.simpl.SimpleJobFactory.newJob:50 - Producing instance of
Job 'DEFAULT.LogJob', class=org.mdeggers.qschedule.utils.DumbJob

2010-10-18 16:08:01,394 DEBUG org.quartz.core.JobRunShell.run:215 -
Calling execute on job DEFAULT.LogJob

2010-10-18 16:10:31,306 DEBUG
org.quartz.simpl.SimpleJobFactory.newJob:50 - Producing instance of
Job 'DEFAULT.LogJob', class=org.mdeggers.qschedule.utils.DumbJob

2010-10-18 16:10:31,307 DEBUG org.quartz.core.JobRunShell.run:215 -
Calling execute on job DEFAULT.LogJob

2010-10-18 16:12:38,487 INFO
org.quartz.core.QuartzScheduler.shutdown:613 - Scheduler
SampleScheduler_$_1 shutting down.

2010-10-18 16:12:38,491 INFO
org.quartz.core.QuartzScheduler.standby:534 - Scheduler
SampleScheduler_$_1 paused.

2010-10-18 16:12:38,492 DEBUG
org.quartz.simpl.SimpleThreadPool.shutdown:366 - shutdown complete

2010-10-18 16:12:38,493 INFO
org.quartz.core.QuartzScheduler.shutdown:683 - Scheduler
SampleScheduler_$_1 shutdown complete.

. . . just my two cents

/mde/



      

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org




---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Tomcat memory leak error launching web app in NetBeans 6.9.1

Posted by Mark Eggers <it...@yahoo.com>.
Once again, I apologize for the wall of text. However, most of it is
pretty quick and dirty code, so it should be easy to skim.

I'm guessing the end result is harmless?

It does seem like a race condition. Everything seems to work fine
until shutdown. When DEBUG is set in logging, you get the following in
catalina.out:

Oct 18, 2010 4:12:38 PM org.apache.catalina.loader.WebappClassLoader 
clearReferencesThreads
SEVERE: The web application [/QSchedule] appears to have started a
thread named [SampleScheduler_Worker-1] but has failed to stop it.
This is very likely to create a memory leak.

Oct 18, 2010 4:12:38 PM org.apache.catalina.loader.WebappClassLoader 
clearReferencesThreads
SEVERE: The web application [/QSchedule] appears to have started a
thread named [SampleScheduler_Worker-2] but has failed to stop it.
This is very likely to create a memory leak.

Oct 18, 2010 4:12:38 PM org.apache.catalina.loader.WebappClassLoader 
clearReferencesThreads
SEVERE: The web application [/QSchedule] appears to have started a
thread named [SampleScheduler_Worker-3] but has failed to stop it.
This is very likely to create a memory leak.

Oct 18, 2010 4:12:38 PM org.apache.catalina.loader.WebappClassLoader loadClass
INFO: Illegal access: this web application instance has been stopped
already.  Could not load java.io.PrintStream.  The eventual following
stack trace is caused by an error thrown for debugging purposes as
well as to attempt to terminate the thread which caused the illegal
access, and has no functional impact.

java.lang.IllegalStateException
at 
org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1531)

at 
org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1491)

at org.apache.log4j.helpers.LogLog.error(LogLog.java:142)
at 
org.apache.log4j.helpers.PatternParser$DatePatternConverter.convert(PatternParser.java:447)

at org.apache.log4j.helpers.PatternConverter.format(PatternConverter.java:64)
at org.apache.log4j.PatternLayout.format(PatternLayout.java:503)
at org.apache.log4j.WriterAppender.subAppend(WriterAppender.java:301)
at org.apache.log4j.WriterAppender.append(WriterAppender.java:159)
at org.apache.log4j.AppenderSkeleton.doAppend(AppenderSkeleton.java:230)
at 
org.apache.log4j.helpers.AppenderAttachableImpl.appendLoopOnAppenders(AppenderAttachableImpl.java:65)

at org.apache.log4j.Category.callAppenders(Category.java:203)
at org.apache.log4j.Category.forcedLog(Category.java:388)
at org.apache.log4j.Category.log(Category.java:853)
at org.slf4j.impl.Log4jLoggerAdapter.debug(Log4jLoggerAdapter.java:204)
at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:595)
log4j:ERROR Error occured while converting date.
java.lang.NullPointerException
at java.lang.AbstractStringBuilder.append(Unknown Source)
at java.lang.StringBuffer.append(Unknown Source)
at org.apache.log4j.helpers.ISO8601DateFormat.format(ISO8601DateFormat.java:132)
at java.text.DateFormat.format(Unknown Source)
at 
org.apache.log4j.helpers.PatternParser$DatePatternConverter.convert(PatternParser.java:444)

at org.apache.log4j.helpers.PatternConverter.format(PatternConverter.java:64)
at org.apache.log4j.PatternLayout.format(PatternLayout.java:503)
at org.apache.log4j.WriterAppender.subAppend(WriterAppender.java:301)
at org.apache.log4j.WriterAppender.append(WriterAppender.java:159)
at org.apache.log4j.AppenderSkeleton.doAppend(AppenderSkeleton.java:230)
at 
org.apache.log4j.helpers.AppenderAttachableImpl.appendLoopOnAppenders(AppenderAttachableImpl.java:65)

at org.apache.log4j.Category.callAppenders(Category.java:203)
at org.apache.log4j.Category.forcedLog(Category.java:388)
at org.apache.log4j.Category.log(Category.java:853)
at org.slf4j.impl.Log4jLoggerAdapter.debug(Log4jLoggerAdapter.java:204)
at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:595)
log4j:ERROR Error occured while converting date.
java.lang.NullPointerException
at java.lang.AbstractStringBuilder.append(Unknown Source)
at java.lang.StringBuffer.append(Unknown Source)
at org.apache.log4j.helpers.ISO8601DateFormat.format(ISO8601DateFormat.java:132)
at java.text.DateFormat.format(Unknown Source)
at 
org.apache.log4j.helpers.PatternParser$DatePatternConverter.convert(PatternParser.java:444)

at org.apache.log4j.helpers.PatternConverter.format(PatternConverter.java:64)
at org.apache.log4j.PatternLayout.format(PatternLayout.java:503)
at org.apache.log4j.WriterAppender.subAppend(WriterAppender.java:301)
at org.apache.log4j.WriterAppender.append(WriterAppender.java:159)
at org.apache.log4j.AppenderSkeleton.doAppend(AppenderSkeleton.java:230)
at 
org.apache.log4j.helpers.AppenderAttachableImpl.appendLoopOnAppenders(AppenderAttachableImpl.java:65)

at org.apache.log4j.Category.callAppenders(Category.java:203)
at org.apache.log4j.Category.forcedLog(Category.java:388)
at org.apache.log4j.Category.log(Category.java:853)
at org.slf4j.impl.Log4jLoggerAdapter.debug(Log4jLoggerAdapter.java:204)
at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:595)
log4j:ERROR Error occured while converting date.
java.lang.NullPointerException
at java.lang.AbstractStringBuilder.append(Unknown Source)
at java.lang.StringBuffer.append(Unknown Source)
at org.apache.log4j.helpers.ISO8601DateFormat.format(ISO8601DateFormat.java:132)
at java.text.DateFormat.format(Unknown Source)
at 
org.apache.log4j.helpers.PatternParser$DatePatternConverter.convert(PatternParser.java:444)

at org.apache.log4j.helpers.PatternConverter.format(PatternConverter.java:64)
at org.apache.log4j.PatternLayout.format(PatternLayout.java:503)
at org.apache.log4j.WriterAppender.subAppend(WriterAppender.java:301)
at org.apache.log4j.WriterAppender.append(WriterAppender.java:159)
at org.apache.log4j.AppenderSkeleton.doAppend(AppenderSkeleton.java:230)
at 
org.apache.log4j.helpers.AppenderAttachableImpl.appendLoopOnAppenders(AppenderAttachableImpl.java:65)

at org.apache.log4j.Category.callAppenders(Category.java:203)
at org.apache.log4j.Category.forcedLog(Category.java:388)
at org.apache.log4j.Category.log(Category.java:853)
at org.slf4j.impl.Log4jLoggerAdapter.debug(Log4jLoggerAdapter.java:204)
at
org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:595)

Here's the relevant portions of the class in question (both 
from org.quartz.simpl.SimpleThreadPool):

    try {
        getLog().debug("WorkerThread is shut down.");
    } catch(Exception e) {
        // ignore to help with a tomcat glitch
    }

And part of the shutdown code - lots of hard-coded wait times:

public void shutdown(boolean waitForJobsToComplete) {
    synchronized (nextRunnableLock) {
        isShutdown = true;
        if(workers == null) // case where the pool wasn't even initialize()ed
            return;
        // signal each worker thread to shut down
        Iterator workerThreads = workers.iterator();
        while(workerThreads.hasNext()) {
            WorkerThread wt = (WorkerThread) workerThreads.next();
            wt.shutdown();
            availWorkers.remove(wt);
        }
        // Give waiting (wait(1000)) worker threads a chance to shut down.
        // Active worker threads will shut down after finishing their
        // current job.
        nextRunnableLock.notifyAll();
        if (waitForJobsToComplete == true) {
            // wait for hand-off in runInThread to complete...
            while(handoffPending) {
                try { nextRunnableLock.wait(100); } catch(Throwable t) {}
            }
            // Wait until all worker threads are shut down
            while (busyWorkers.size() > 0) {
                WorkerThread wt = (WorkerThread) busyWorkers.getFirst();
                try {
                    getLog().debug(
                            "Waiting for thread " + wt.getName()
                                    + " to shut down");
                    // note: with waiting infinite time the
                    // application may appear to 'hang'.
                    nextRunnableLock.wait(2000);
                } catch (InterruptedException ex) {
                }
            }
            getLog().debug("shutdown complete");
        }
    }
}

Looking at the above code, there's a wait of 2.1 seconds per thread?
If that's the case, then the 3 threads will take up to 6.3 seconds
while waiting.

What's odd is that I don't see the entry: "Waiting for thread " name "
to shut down" in any of the logs.

Here's some admittedly ugly code I put together:

The listener:

package org.mdeggers.qschedule.utils;

import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.Properties;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import org.apache.log4j.Logger;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.Trigger;
import org.quartz.TriggerUtils;
import org.quartz.impl.StdSchedulerFactory;

/**
 * Web application lifecycle listener.
 * @author mdeggers
 */
public class DIYCronListener implements ServletContextListener {

    private static final Logger log = Logger.getLogger(DIYCronListener.class);
    private SchedulerFactory schedFactory = null;
    private Scheduler scheduler = null;

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        int schedInterval = 
Integer.parseInt(sce.getServletContext().getInitParameter("quartz:schedule-interval"));

        String propsFile = 
sce.getServletContext().getInitParameter("quartz:config-file");
        Properties props = new Properties();

        // loading properties file
        InputStream in = 
this.getClass().getClassLoader().getResourceAsStream(propsFile);
        try {
            props.load(in);
        } catch (IOException ex) {
            log.fatal("Failed to load properties file: ", ex);
        }
        try {
            in.close();
        } catch (IOException ex) {
            log.fatal("Failed to close properties file: ", ex);
        }

        // creating the scheduler factory
        try {
            schedFactory = new StdSchedulerFactory(props);
            log.info("Got scheduler factory with the appropriate properties");
            // getting the scheduler
            try {
                scheduler = schedFactory.getScheduler();
                log.info("Got scheduler from schedule factory");
            } catch (SchedulerException ex) {
                log.fatal("Failed to get a scheduler: ", ex);
            }
        } catch (SchedulerException ex) {
            log.fatal("Failed to get a scheduler factory: ", ex);
        }

        // creating the job - yep, hardcoded
        String jobName = "LogJob";
        JobDetail jobDetail = new JobDetail(jobName, DumbJob.class);

        // creating the trigger
        Trigger trigger = TriggerUtils.makeSecondlyTrigger(schedInterval);
        trigger.setStartTime(new Date());
        trigger.setName(jobName);

        // now try to start the scheduler and add the job
        if (scheduler != null) {
            try {
                scheduler.start();
                log.info("Scheduler started");
                // try to add the job
                try {
                    Date jobDate = scheduler.scheduleJob(jobDetail, trigger);
                    log.info("Job started: " + jobName + " on " + 
jobDate.toString());
                } catch (SchedulerException ex) {
                    log.fatal("Failed to add job: ", ex);
                }
            } catch (SchedulerException ex) {
                log.fatal("Failed to start scheduler", ex);
            }
        }
        log.info("I have started.");
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        boolean qWait = 
Boolean.parseBoolean(sce.getServletContext().getInitParameter("quartz:shutdown-wait"));

        try {
            if (scheduler.isStarted()) {
                try {
                    scheduler.shutdown(qWait);
                    log.info("Shutting down scheduler");
                } catch (SchedulerException ex) {
                    log.fatal("Failed to shut down scheduler: ", ex);
                }
            } else {
                log.info("Scheduler returns not started");
            }
        } catch (SchedulerException ex) {
            log.fatal("Could not determine if scheduler was started", ex);
        }
    }
}

The job:

package org.mdeggers.qschedule.utils;

import org.apache.log4j.Logger;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

/**
 *
 * @author mdeggers
 */
public class DumbJob implements Job {
    private static final Logger log = Logger.getLogger(DumbJob.class);
    
    public DumbJob() {
    }

    @Override
    public void execute(JobExecutionContext context) throws 
JobExecutionException {
        log.info("Hello from the Dumb job.");
    }
}

The log4j.xml file:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration PUBLIC 'PUBLIC:-//log4j/log4j Configuration//EN' 
'log4j.dtd'>
<log4j:configuration>
    <appender name="FA" class="org.apache.log4j.FileAppender">
        <param name="File" value="${log4j.home}/qschedule.log"/>
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%d %-5p %c.%M:%L - %m%n"/>
        </layout>
    </appender>
    <appender name="QA" class="org.apache.log4j.FileAppender">
        <param name="File" value="${log4j.home}/quartz-debug.log"/>
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%d %-5p %c.%M:%L - %m%n"/>
        </layout>
    </appender>
<!-- debug for quartz scheduler - trying to find out where the holdup is -->
    <logger name="org.quartz">
        <level value="DEBUG"/>
        <appender-ref ref="QA"/>
    </logger>
<!-- info from my classes -->
    <logger name="org.mdeggers">
        <level value="INFO"/>
        <appender-ref ref="FA"/>
    </logger>
</log4j:configuration>

The properties file (quartz.properties)

org.quartz.scheduler.instanceName = SampleScheduler
org.quartz.scheduler.instanceId = 1
org.quartz.scheduler.rmi.export = false
org.quartz.scheduler.rmi.proxy = false

org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 3

org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore
org.quartz.scheduler.skipUpdateCheck = true

And the corresponding parts of the web.xml file:

<context-param>
    <description>Quartz scheduler configuration file</description>
    <param-name>quartz:config-file</param-name>
    <param-value>quartz.properties</param-value>
</context-param>
<context-param>
    <description>Time in seconds between scheduler executions</description>
    <param-name>quartz:schedule-interval</param-name>
    <param-value>150</param-value>
</context-param>
<context-param>
    <description>Quartz scheduler wait to finish jobs before 
shutdown</description>
    <param-name>quartz:shutdown-wait</param-name>
    <param-value>true</param-value>
</context-param>
<listener>
     <description>Do it yourself Quartz Scheduler</description>
   
 <listener-class>org.mdeggers.qschedule.utils.DIYCronListener</listener-class>
</listener>

The log files generated look reasonable.

qschedule.log:

2010-10-18 16:08:01,067 INFO 
  org.mdeggers.qschedule.utils.DIYCronListener.contextInitialized:50
  - Got scheduler factory with the appropriate properties
2010-10-18 16:08:01,289 INFO
  org.mdeggers.qschedule.utils.DIYCronListener.contextInitialized:54
  - Got scheduler from schedule factory
2010-10-18 16:08:01,308 INFO
  org.mdeggers.qschedule.utils.DIYCronListener.contextInitialized:75
  - Scheduler started
2010-10-18 16:08:01,335 INFO
  org.mdeggers.qschedule.utils.DIYCronListener.contextInitialized:79
  - Job started: LogJob on Mon Oct 18 16:08:01 PDT 2010
2010-10-18 16:08:01,336 INFO
  org.mdeggers.qschedule.utils.DIYCronListener.contextInitialized:87
  - I have started.
2010-10-18 16:08:01,394 INFO
  org.mdeggers.qschedule.utils.DumbJob.execute:25
  - Hello from the Dumb job.
2010-10-18 16:10:31,309 INFO
  org.mdeggers.qschedule.utils.DumbJob.execute:25
  - Hello from the Dumb job.
2010-10-18 16:12:38,494 INFO
  org.mdeggers.qschedule.utils.DIYCronListener.contextDestroyed:97
  - Shutting down scheduler

quartz-debug.log:

2010-10-18 16:08:01,276 INFO
org.quartz.core.SchedulerSignalerImpl.<init>:60 - Initialized
Scheduler Signaller of type: class org.quartz.core.SchedulerSignalerImpl

2010-10-18 16:08:01,277 INFO
org.quartz.core.QuartzScheduler.<init>:219 - Quartz Scheduler v.1.8.3 created.

2010-10-18 16:08:01,281 INFO org.quartz.simpl.RAMJobStore.initialize:139 - 
RAMJobStore initialized.

2010-10-18 16:08:01,284 INFO
org.quartz.core.QuartzScheduler.initialize:241 - Scheduler meta-data:
Quartz Scheduler (v1.8.3) 'SampleScheduler' with instanceId '1'

  Scheduler class: 'org.quartz.core.QuartzScheduler' - running locally.
  NOT STARTED.
  Currently in standby mode.
  Number of jobs executed: 0
  Using thread pool 'org.quartz.simpl.SimpleThreadPool' - with 3 threads.
  Using job-store 'org.quartz.simpl.RAMJobStore' - which does not support 
persistence.
  and is not clustered.

2010-10-18 16:08:01,286 INFO
org.quartz.impl.StdSchedulerFactory.instantiate:1275 - Quartz
scheduler 'SampleScheduler' initialized from an externally provided
properties instance.

2010-10-18 16:08:01,288 INFO
org.quartz.impl.StdSchedulerFactory.instantiate:1279 - Quartz
scheduler version: 1.8.3

2010-10-18 16:08:01,306 INFO org.quartz.core.QuartzScheduler.start:497
- Scheduler SampleScheduler_$_1 started.

2010-10-18 16:08:01,346 DEBUG
org.quartz.simpl.SimpleJobFactory.newJob:50 - Producing instance of
Job 'DEFAULT.LogJob', class=org.mdeggers.qschedule.utils.DumbJob

2010-10-18 16:08:01,394 DEBUG org.quartz.core.JobRunShell.run:215 -
Calling execute on job DEFAULT.LogJob

2010-10-18 16:10:31,306 DEBUG
org.quartz.simpl.SimpleJobFactory.newJob:50 - Producing instance of
Job 'DEFAULT.LogJob', class=org.mdeggers.qschedule.utils.DumbJob

2010-10-18 16:10:31,307 DEBUG org.quartz.core.JobRunShell.run:215 -
Calling execute on job DEFAULT.LogJob

2010-10-18 16:12:38,487 INFO
org.quartz.core.QuartzScheduler.shutdown:613 - Scheduler
SampleScheduler_$_1 shutting down.

2010-10-18 16:12:38,491 INFO
org.quartz.core.QuartzScheduler.standby:534 - Scheduler
SampleScheduler_$_1 paused.

2010-10-18 16:12:38,492 DEBUG
org.quartz.simpl.SimpleThreadPool.shutdown:366 - shutdown complete

2010-10-18 16:12:38,493 INFO
org.quartz.core.QuartzScheduler.shutdown:683 - Scheduler
SampleScheduler_$_1 shutdown complete.

. . . just my two cents

/mde/



      

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Tomcat memory leak error launching web app in NetBeans 6.9.1

Posted by Mark Eggers <it...@yahoo.com>.
That's what I've read and from the code it's the default.

I'm hacking together a listener that rolls the entire chain from scratch rather 
than depending on the Quartz-supplied listener. I'll add some debugging logging 
and see what happens.

I might also try just creating the SchedulerFactory first, then getting a 
scheduler, then starting the scheduler, and finally adding a job.


----- Original Message ----
From: Pid <pi...@pidster.com>
To: Tomcat Users List <us...@tomcat.apache.org>
Sent: Mon, October 18, 2010 3:15:28 PM
Subject: Re: Tomcat memory leak error launching web app in NetBeans 6.9.1

On 18/10/2010 23:02, Mark Thomas wrote:
> On 18/10/2010 16:56, Mark Thomas wrote:
>> On 18/10/2010 12:05, Mark Eggers wrote:
>>> I saw a mention of this on the Quartz forums. People there seem to think it's a 
>>>
>>> race condition between Quartz's scheduler shutdown and Tomcat's thread memory 
>
>>> leak reporting.
>>
>> That is certainly possible. There was a reason I wrote the message "This
>> is very likely to create a memory leak." rather than "There is a memory
>> leak."
>>
>> Options to consider:
>> - is there a way to perform a synchronous shutdown of the scheduler?
>> - can you detect if the scheduler has not shutdown an loop (for a
>> limited time) waiting for it to finish?
> 
> Something that occurred to me just after I hit send. These threads
> really need to finish up *before* Tomcat shuts down the context. Tomcat
> does a bunch of clean-up stuff to prevent memory leaks and if
> application code is still running when the clean-up code runs the
> clean-up could easily fail.

Calling scheduler.shutdown(true); /should/ cause it to block & wait for
existing jobs to finish.

The Quartz supplied Listener does appear to do this:

http://svn.terracotta.org/fisheye/browse/Quartz/trunk/quartz/src/main/java/org/quartz/ee/servlet/QuartzInitializerListener.java?r=HEAD



p



      

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Tomcat memory leak error launching web app in NetBeans 6.9.1

Posted by Pid <pi...@pidster.com>.
On 18/10/2010 23:02, Mark Thomas wrote:
> On 18/10/2010 16:56, Mark Thomas wrote:
>> On 18/10/2010 12:05, Mark Eggers wrote:
>>> I saw a mention of this on the Quartz forums. People there seem to think it's a 
>>> race condition between Quartz's scheduler shutdown and Tomcat's thread memory 
>>> leak reporting.
>>
>> That is certainly possible. There was a reason I wrote the message "This
>> is very likely to create a memory leak." rather than "There is a memory
>> leak."
>>
>> Options to consider:
>> - is there a way to perform a synchronous shutdown of the scheduler?
>> - can you detect if the scheduler has not shutdown an loop (for a
>> limited time) waiting for it to finish?
> 
> Something that occurred to me just after I hit send. These threads
> really need to finish up *before* Tomcat shuts down the context. Tomcat
> does a bunch of clean-up stuff to prevent memory leaks and if
> application code is still running when the clean-up code runs the
> clean-up could easily fail.

Calling scheduler.shutdown(true); /should/ cause it to block & wait for
existing jobs to finish.

The Quartz supplied Listener does appear to do this:

http://svn.terracotta.org/fisheye/browse/Quartz/trunk/quartz/src/main/java/org/quartz/ee/servlet/QuartzInitializerListener.java?r=HEAD


p

Re: Tomcat memory leak error launching web app in NetBeans 6.9.1

Posted by Mark Thomas <ma...@apache.org>.
On 18/10/2010 16:56, Mark Thomas wrote:
> On 18/10/2010 12:05, Mark Eggers wrote:
>> I saw a mention of this on the Quartz forums. People there seem to think it's a 
>> race condition between Quartz's scheduler shutdown and Tomcat's thread memory 
>> leak reporting.
> 
> That is certainly possible. There was a reason I wrote the message "This
> is very likely to create a memory leak." rather than "There is a memory
> leak."
> 
> Options to consider:
> - is there a way to perform a synchronous shutdown of the scheduler?
> - can you detect if the scheduler has not shutdown an loop (for a
> limited time) waiting for it to finish?

Something that occurred to me just after I hit send. These threads
really need to finish up *before* Tomcat shuts down the context. Tomcat
does a bunch of clean-up stuff to prevent memory leaks and if
application code is still running when the clean-up code runs the
clean-up could easily fail.

Mark



---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Tomcat memory leak error launching web app in NetBeans 6.9.1

Posted by Mark Thomas <ma...@apache.org>.
On 18/10/2010 12:05, Mark Eggers wrote:
> I saw a mention of this on the Quartz forums. People there seem to think it's a 
> race condition between Quartz's scheduler shutdown and Tomcat's thread memory 
> leak reporting.

That is certainly possible. There was a reason I wrote the message "This
is very likely to create a memory leak." rather than "There is a memory
leak."

Options to consider:
- is there a way to perform a synchronous shutdown of the scheduler?
- can you detect if the scheduler has not shutdown an loop (for a
limited time) waiting for it to finish?

Mark



---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Tomcat memory leak error launching web app in NetBeans 6.9.1

Posted by Pid <pi...@pidster.com>.
On 18/10/2010 18:19, Martin O'Shea wrote:
> Thanks Mark. Your test seems to bear out the issue I'm having.
> 
> For information: I have my own ServletContextListener which has a
> contextDestroyed method as follows:
> 
> @Override
>     public void contextDestroyed(ServletContextEvent contextEvent) {
>         context = contextEvent.getServletContext();
>         Scheduler_Controller sc = new Scheduler_Controller();
> 
> 
>         // Is scheduler stopped?
>         try {
>             if (sc.isSchedulerStopped()) {
>                 System.out.println("The scheduler is already stopped.");
>             }
>             else {
>                 try {
>                     sc.stopScheduler();
>                     System.out.println("The scheduler has been stopped.");
> 
>                 }
>                 catch(Exception ex) {
>                     logger.error("Error stopping scheduler\n" + ex);
>                 }
>             }
>         }
>         catch(Exception ex) {
>             logger.error("Error stopping scheduler\n", ex);
>         }
>     }
> 
> Methods isSchedulerStopped and stopScheduler follow:
> 
> public boolean isSchedulerStopped() throws Exception {
>         SchedulerFactory sf = new StdSchedulerFactory();
>         Scheduler scheduler = sf.getScheduler();
>         scheduler = StdSchedulerFactory.getDefaultScheduler();

Why create a new factory and object each time, rather than when the
owning object is created - in the constructor?

Why use a controller object?  It would be simpler to just create it all
in the ServletContextListener, wouldn't it?


p

>         if (scheduler.isShutdown()) {
>             return true;
>         }
>         else {
>             return false;
>         }
>     }
> 
> public void stopScheduler() throws Exception {
>         SchedulerFactory sf = new StdSchedulerFactory();
>         Scheduler scheduler = sf.getScheduler();
>         scheduler = StdSchedulerFactory.getDefaultScheduler();
> 
>         Scheduler_Job sj = null;
> 
>         // First scheduled job.
>         try {
>             sj = Scheduler_Job_DB.get(1);
>             scheduler.unscheduleJob(sj.getJobName(),
> scheduler.DEFAULT_GROUP);
>             System.out.println("Job " + sj.getJobName() + " unsubmitted.");
>         }
>         catch(Exception ex){
>             logger.error("Error unsubmitting job " + sj.getJobName() + "\n",
> ex);
>         }
> 
>         // Second scheduled job.
>         try {
>             sj = Scheduler_Job_DB.get(2);
>             scheduler.unscheduleJob(sj.getJobName(),
> scheduler.DEFAULT_GROUP);
>             System.out.println("Job " + sj.getJobName() + " unsubmitted.");
>         }
>         catch(Exception ex){
>             logger.error("Error unsubmitting job " + sj.getJobName() + "\n",
> ex);
>         }
> 
>         scheduler.shutdown(true);
>         if (scheduler.isShutdown()) {
>             System.out.println("Scheduler stopped");
>         }
>     }
> 
> So I think that according to these, the scheduler should end 'gracefully' by
> unsubmitting the jobs and by using scheduler.shutdown(true);.
> 
> If I'm wrong, please let me know.
> 
> -----Original Message-----
> From: Mark Eggers [mailto:its_toasted@yahoo.com] 
> Sent: 18 Oct 2010 18 06
> To: Tomcat Users List
> Subject: Re: Tomcat memory leak error launching web app in NetBeans 6.9.1
> 
> I saw a mention of this on the Quartz forums. People there seem to think
> it's a 
> race condition between Quartz's scheduler shutdown and Tomcat's thread
> memory 
> leak reporting.
> 
> I wrote a quick Quartz scheduler (1.8.3) application. It does the following:
> 
> 1. Uses the supplied listener to put a scheduler factory in the servlet
> context 
>    (org.quartz.ee.servlet.QuartzInitializerListener)
> 2. Uses another listener to add a job that writes to a log file every 5
> minutes
> 3. Uses the provided listener
> (org.quartz.ee.servlet.QuartzInitializerListener) 
> to shut down 
>    all schedulers
> 
> The supplied listener is configured via parameters to start the scheduler on
> 
> startup, and shut down the scheduler on application termination.
> 
> When I watch this using visualvm (1.3.1) on Tomcat 6.0.18 and 6.0.29, I see
> the 
> four threads that are started by Quartz vanish when the application is 
> undeployed. Tomcat reports the SEVERE error for some of these threads in 
> catalina.out. I ran the test twice and I think that Tomcat reported
> different 
> threads on each run (didn't save the log files). I also didn't look for any 
> stray classes left after the application was undeployed.
> 
> The supplied listener can be configured to not start or shut down the
> scheduler. 
> Starting and shutting down the scheduler can then be managed by the second 
> listener (that adds the job). I've not tried this yet.
> 
> Finally, there are two ways to shut down the scheduler. The default
> (graceful) 
> way waits for any pending jobs to complete. Calling shutdown(false)
> immediately 
> terminates the scheduler. This doesn't seem to be configurable using the 
> supplied listener, so the scheduler would have to be managed by the second 
> listener.
> 
> Environment:
> 
> OS:      Fedora 13 2.6.34.7-56.fc13.i686
> Java:    Oracle/Sun Java JRE/JDK 1.6.0_22
> IDE:     NetBeans 6.9.1 / Maven 2.2.1
> Tomcat:  6.0.29
>          6.0.18
> Quartz:  1.8.3
> Monitor: VisualVM 1.3.1 (https://visualvm.dev.java.net/)
> 
> If I have some time today, I'll try some variations.
> 
> . . . . just my two cents.
> 
> /mde/
> ----- Original Message ----
> From: Martin O'Shea <ap...@dsl.pipex.com>
> To: Tomcat Users List <us...@tomcat.apache.org>
> Sent: Mon, October 18, 2010 5:52:08 AM
> Subject: RE: Tomcat memory leak error launching web app in NetBeans 6.9.1
> 
> You're probably correct and assuming this is to do with Quartz which it
> seems to 
> be, are you aware of any similar cases or remedies?
> 
> -----Original Message-----
> From: Christopher Schultz [mailto:chris@christopherschultz.net] 
> Sent: 18 Oct 2010 13 49
> To: Tomcat Users List
> Subject: Re: Tomcat memory leak error launching web app in NetBeans 6.9.1
> 
> Martin,
> 
> On 10/16/2010 11:11 AM, Martin O'Shea wrote:
>> Definitely seems to be when the web application in question is terminated,
> 
>> rather than Tomcat itself. And all indications are the listener that
> handles the 
>> scheduler.
> 
>> And I've tried another similar application which gives messages of the
> same 
>> kind.
> 
>> And yet both apps have worked under other environments.
> 
> Note that the leak detection has been added and improved in recent
> Tomcat versions. It's possible that this problem has always been there,
> you're just never been notified about it.
> 
> -chris

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org




---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org




---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org




---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org



RE: Tomcat memory leak error launching web app in NetBeans 6.9.1

Posted by Martin O'Shea <ap...@dsl.pipex.com>.
Thanks Mark. Your test seems to bear out the issue I'm having.

For information: I have my own ServletContextListener which has a
contextDestroyed method as follows:

@Override
    public void contextDestroyed(ServletContextEvent contextEvent) {
        context = contextEvent.getServletContext();
        Scheduler_Controller sc = new Scheduler_Controller();


        // Is scheduler stopped?
        try {
            if (sc.isSchedulerStopped()) {
                System.out.println("The scheduler is already stopped.");
            }
            else {
                try {
                    sc.stopScheduler();
                    System.out.println("The scheduler has been stopped.");

                }
                catch(Exception ex) {
                    logger.error("Error stopping scheduler\n" + ex);
                }
            }
        }
        catch(Exception ex) {
            logger.error("Error stopping scheduler\n", ex);
        }
    }

Methods isSchedulerStopped and stopScheduler follow:

public boolean isSchedulerStopped() throws Exception {
        SchedulerFactory sf = new StdSchedulerFactory();
        Scheduler scheduler = sf.getScheduler();
        scheduler = StdSchedulerFactory.getDefaultScheduler();
        if (scheduler.isShutdown()) {
            return true;
        }
        else {
            return false;
        }
    }

public void stopScheduler() throws Exception {
        SchedulerFactory sf = new StdSchedulerFactory();
        Scheduler scheduler = sf.getScheduler();
        scheduler = StdSchedulerFactory.getDefaultScheduler();

        Scheduler_Job sj = null;

        // First scheduled job.
        try {
            sj = Scheduler_Job_DB.get(1);
            scheduler.unscheduleJob(sj.getJobName(),
scheduler.DEFAULT_GROUP);
            System.out.println("Job " + sj.getJobName() + " unsubmitted.");
        }
        catch(Exception ex){
            logger.error("Error unsubmitting job " + sj.getJobName() + "\n",
ex);
        }

        // Second scheduled job.
        try {
            sj = Scheduler_Job_DB.get(2);
            scheduler.unscheduleJob(sj.getJobName(),
scheduler.DEFAULT_GROUP);
            System.out.println("Job " + sj.getJobName() + " unsubmitted.");
        }
        catch(Exception ex){
            logger.error("Error unsubmitting job " + sj.getJobName() + "\n",
ex);
        }

        scheduler.shutdown(true);
        if (scheduler.isShutdown()) {
            System.out.println("Scheduler stopped");
        }
    }

So I think that according to these, the scheduler should end 'gracefully' by
unsubmitting the jobs and by using scheduler.shutdown(true);.

If I'm wrong, please let me know.

-----Original Message-----
From: Mark Eggers [mailto:its_toasted@yahoo.com] 
Sent: 18 Oct 2010 18 06
To: Tomcat Users List
Subject: Re: Tomcat memory leak error launching web app in NetBeans 6.9.1

I saw a mention of this on the Quartz forums. People there seem to think
it's a 
race condition between Quartz's scheduler shutdown and Tomcat's thread
memory 
leak reporting.

I wrote a quick Quartz scheduler (1.8.3) application. It does the following:

1. Uses the supplied listener to put a scheduler factory in the servlet
context 
   (org.quartz.ee.servlet.QuartzInitializerListener)
2. Uses another listener to add a job that writes to a log file every 5
minutes
3. Uses the provided listener
(org.quartz.ee.servlet.QuartzInitializerListener) 
to shut down 
   all schedulers

The supplied listener is configured via parameters to start the scheduler on

startup, and shut down the scheduler on application termination.

When I watch this using visualvm (1.3.1) on Tomcat 6.0.18 and 6.0.29, I see
the 
four threads that are started by Quartz vanish when the application is 
undeployed. Tomcat reports the SEVERE error for some of these threads in 
catalina.out. I ran the test twice and I think that Tomcat reported
different 
threads on each run (didn't save the log files). I also didn't look for any 
stray classes left after the application was undeployed.

The supplied listener can be configured to not start or shut down the
scheduler. 
Starting and shutting down the scheduler can then be managed by the second 
listener (that adds the job). I've not tried this yet.

Finally, there are two ways to shut down the scheduler. The default
(graceful) 
way waits for any pending jobs to complete. Calling shutdown(false)
immediately 
terminates the scheduler. This doesn't seem to be configurable using the 
supplied listener, so the scheduler would have to be managed by the second 
listener.

Environment:

OS:      Fedora 13 2.6.34.7-56.fc13.i686
Java:    Oracle/Sun Java JRE/JDK 1.6.0_22
IDE:     NetBeans 6.9.1 / Maven 2.2.1
Tomcat:  6.0.29
         6.0.18
Quartz:  1.8.3
Monitor: VisualVM 1.3.1 (https://visualvm.dev.java.net/)

If I have some time today, I'll try some variations.

. . . . just my two cents.

/mde/
----- Original Message ----
From: Martin O'Shea <ap...@dsl.pipex.com>
To: Tomcat Users List <us...@tomcat.apache.org>
Sent: Mon, October 18, 2010 5:52:08 AM
Subject: RE: Tomcat memory leak error launching web app in NetBeans 6.9.1

You're probably correct and assuming this is to do with Quartz which it
seems to 
be, are you aware of any similar cases or remedies?

-----Original Message-----
From: Christopher Schultz [mailto:chris@christopherschultz.net] 
Sent: 18 Oct 2010 13 49
To: Tomcat Users List
Subject: Re: Tomcat memory leak error launching web app in NetBeans 6.9.1

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Martin,

On 10/16/2010 11:11 AM, Martin O'Shea wrote:
> Definitely seems to be when the web application in question is terminated,

>rather than Tomcat itself. And all indications are the listener that
handles the 
>scheduler.
> 
> And I've tried another similar application which gives messages of the
same 
>kind.
> 
> And yet both apps have worked under other environments.

Note that the leak detection has been added and improved in recent
Tomcat versions. It's possible that this problem has always been there,
you're just never been notified about it.

- -chris
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (MingW32)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAky8QkkACgkQ9CaO5/Lv0PAwNACfVwsejeJhSe3CajEWqQraiXTf
amwAoI8Kl+4V07E7Tv4Axn8ASiJRq8Pm
=9dxR
-----END PGP SIGNATURE-----

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org




---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


      

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org




---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Tomcat memory leak error launching web app in NetBeans 6.9.1

Posted by Mark Eggers <it...@yahoo.com>.
I saw a mention of this on the Quartz forums. People there seem to think it's a 
race condition between Quartz's scheduler shutdown and Tomcat's thread memory 
leak reporting.

I wrote a quick Quartz scheduler (1.8.3) application. It does the following:

1. Uses the supplied listener to put a scheduler factory in the servlet context 
   (org.quartz.ee.servlet.QuartzInitializerListener)
2. Uses another listener to add a job that writes to a log file every 5 minutes
3. Uses the provided listener (org.quartz.ee.servlet.QuartzInitializerListener) 
to shut down 
   all schedulers

The supplied listener is configured via parameters to start the scheduler on 
startup, and shut down the scheduler on application termination.

When I watch this using visualvm (1.3.1) on Tomcat 6.0.18 and 6.0.29, I see the 
four threads that are started by Quartz vanish when the application is 
undeployed. Tomcat reports the SEVERE error for some of these threads in 
catalina.out. I ran the test twice and I think that Tomcat reported different 
threads on each run (didn't save the log files). I also didn't look for any 
stray classes left after the application was undeployed.

The supplied listener can be configured to not start or shut down the scheduler. 
Starting and shutting down the scheduler can then be managed by the second 
listener (that adds the job). I've not tried this yet.

Finally, there are two ways to shut down the scheduler. The default (graceful) 
way waits for any pending jobs to complete. Calling shutdown(false) immediately 
terminates the scheduler. This doesn't seem to be configurable using the 
supplied listener, so the scheduler would have to be managed by the second 
listener.

Environment:

OS:      Fedora 13 2.6.34.7-56.fc13.i686
Java:    Oracle/Sun Java JRE/JDK 1.6.0_22
IDE:     NetBeans 6.9.1 / Maven 2.2.1
Tomcat:  6.0.29
         6.0.18
Quartz:  1.8.3
Monitor: VisualVM 1.3.1 (https://visualvm.dev.java.net/)

If I have some time today, I'll try some variations.

. . . . just my two cents.

/mde/
----- Original Message ----
From: Martin O'Shea <ap...@dsl.pipex.com>
To: Tomcat Users List <us...@tomcat.apache.org>
Sent: Mon, October 18, 2010 5:52:08 AM
Subject: RE: Tomcat memory leak error launching web app in NetBeans 6.9.1

You're probably correct and assuming this is to do with Quartz which it seems to 
be, are you aware of any similar cases or remedies?

-----Original Message-----
From: Christopher Schultz [mailto:chris@christopherschultz.net] 
Sent: 18 Oct 2010 13 49
To: Tomcat Users List
Subject: Re: Tomcat memory leak error launching web app in NetBeans 6.9.1

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Martin,

On 10/16/2010 11:11 AM, Martin O'Shea wrote:
> Definitely seems to be when the web application in question is terminated, 
>rather than Tomcat itself. And all indications are the listener that handles the 
>scheduler.
> 
> And I've tried another similar application which gives messages of the same 
>kind.
> 
> And yet both apps have worked under other environments.

Note that the leak detection has been added and improved in recent
Tomcat versions. It's possible that this problem has always been there,
you're just never been notified about it.

- -chris
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (MingW32)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAky8QkkACgkQ9CaO5/Lv0PAwNACfVwsejeJhSe3CajEWqQraiXTf
amwAoI8Kl+4V07E7Tv4Axn8ASiJRq8Pm
=9dxR
-----END PGP SIGNATURE-----

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org




---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


      

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


RE: Tomcat memory leak error launching web app in NetBeans 6.9.1

Posted by Martin O'Shea <ap...@dsl.pipex.com>.
You're probably correct and assuming this is to do with Quartz which it seems to be, are you aware of any similar cases or remedies?

-----Original Message-----
From: Christopher Schultz [mailto:chris@christopherschultz.net] 
Sent: 18 Oct 2010 13 49
To: Tomcat Users List
Subject: Re: Tomcat memory leak error launching web app in NetBeans 6.9.1

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Martin,

On 10/16/2010 11:11 AM, Martin O'Shea wrote:
> Definitely seems to be when the web application in question is terminated, rather than Tomcat itself. And all indications are the listener that handles the scheduler.
> 
> And I've tried another similar application which gives messages of the same kind.
> 
> And yet both apps have worked under other environments.

Note that the leak detection has been added and improved in recent
Tomcat versions. It's possible that this problem has always been there,
you're just never been notified about it.

- -chris
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (MingW32)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAky8QkkACgkQ9CaO5/Lv0PAwNACfVwsejeJhSe3CajEWqQraiXTf
amwAoI8Kl+4V07E7Tv4Axn8ASiJRq8Pm
=9dxR
-----END PGP SIGNATURE-----

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org




---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Tomcat memory leak error launching web app in NetBeans 6.9.1

Posted by Christopher Schultz <ch...@christopherschultz.net>.
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Martin,

On 10/16/2010 11:11 AM, Martin O'Shea wrote:
> Definitely seems to be when the web application in question is terminated, rather than Tomcat itself. And all indications are the listener that handles the scheduler.
> 
> And I've tried another similar application which gives messages of the same kind.
> 
> And yet both apps have worked under other environments.

Note that the leak detection has been added and improved in recent
Tomcat versions. It's possible that this problem has always been there,
you're just never been notified about it.

- -chris
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (MingW32)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAky8QkkACgkQ9CaO5/Lv0PAwNACfVwsejeJhSe3CajEWqQraiXTf
amwAoI8Kl+4V07E7Tv4Axn8ASiJRq8Pm
=9dxR
-----END PGP SIGNATURE-----

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


RE: Tomcat memory leak error launching web app in NetBeans 6.9.1

Posted by Martin O'Shea <ap...@dsl.pipex.com>.
Definitely seems to be when the web application in question is terminated, rather than Tomcat itself. And all indications are the listener that handles the scheduler.

And I've tried another similar application which gives messages of the same kind.

And yet both apps have worked under other environments.

-----Original Message-----
From: Caldarale, Charles R [mailto:Chuck.Caldarale@unisys.com] 
Sent: 16 Oct 2010 15 53
To: Tomcat Users List
Subject: RE: Tomcat memory leak error launching web app in NetBeans 6.9.1

> From: Martin O'Shea [mailto:appy74@dsl.pipex.com] 
> Subject: RE: Tomcat memory leak error launching web app in NetBeans 6.9.1

> When the application is terminated, e.g. when the server 
> is stopped, appropriate messages are issued to confirm 
> that the scheduler has stopped.

What about when it's just the webapp being stopped, not the whole server?

Try stopping just the webapp, then take a thread dump of Tomcat to see if the quartz threads are really still there.  If they are, then the shutdown logic in the listener isn't working.

> And the configuration is the only one on this PC, Tomcat 6.0.26 
> using JVM 1.6.0_21-b07. I'm using JDK 1.6.0_21.

IDEs have a nasty habit of substituting their own Tomcat and webapp configurations rather than using the ones you think you've set up.  You won't find additional Tomcat or JDK installations, just behavior that's not consistent with what you configured.

 - Chuck


THIS COMMUNICATION MAY CONTAIN CONFIDENTIAL AND/OR OTHERWISE PROPRIETARY MATERIAL and is thus for use only by the intended recipient. If you received this in error, please contact the sender and delete the e-mail and its attachments from all computers.




---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


RE: Tomcat memory leak error launching web app in NetBeans 6.9.1

Posted by "Caldarale, Charles R" <Ch...@unisys.com>.
> From: Martin O'Shea [mailto:appy74@dsl.pipex.com] 
> Subject: RE: Tomcat memory leak error launching web app in NetBeans 6.9.1

> When the application is terminated, e.g. when the server 
> is stopped, appropriate messages are issued to confirm 
> that the scheduler has stopped.

What about when it's just the webapp being stopped, not the whole server?

Try stopping just the webapp, then take a thread dump of Tomcat to see if the quartz threads are really still there.  If they are, then the shutdown logic in the listener isn't working.

> And the configuration is the only one on this PC, Tomcat 6.0.26 
> using JVM 1.6.0_21-b07. I'm using JDK 1.6.0_21.

IDEs have a nasty habit of substituting their own Tomcat and webapp configurations rather than using the ones you think you've set up.  You won't find additional Tomcat or JDK installations, just behavior that's not consistent with what you configured.

 - Chuck


THIS COMMUNICATION MAY CONTAIN CONFIDENTIAL AND/OR OTHERWISE PROPRIETARY MATERIAL and is thus for use only by the intended recipient. If you received this in error, please contact the sender and delete the e-mail and its attachments from all computers.


RE: Tomcat memory leak error launching web app in NetBeans 6.9.1

Posted by Martin O'Shea <ap...@dsl.pipex.com>.
I know that the ServletContextListener is running when the application starts because of messages issued from it. It is also calling the two Quartz jobs which appear to be running normally as well. When the application is terminated, e.g. when the server is stopped, appropriate messages are issued to confirm that the scheduler has stopped. Then come the messages about the memory leak.

And the configuration is the only one on this PC, Tomcat 6.0.26 using JVM 1.6.0_21-b07. I'm using JDK 1.6.0_21.

-----Original Message-----
From: Caldarale, Charles R [mailto:Chuck.Caldarale@unisys.com] 
Sent: 16 Oct 2010 15 30
To: Tomcat Users List
Subject: RE: Tomcat memory leak error launching web app in NetBeans 6.9.1

> From: Martin O'Shea [mailto:appy74@dsl.pipex.com] 
> Subject: RE: Tomcat memory leak error launching web app in NetBeans 6.9.1

> I have NetBeans's Deploy on Save set. This seems to restart 
> the server with the current objects.

No, it restarts the webapp, not the server.

> But what I don't understand is why the ServletContextListener 
> which handles Quartz jobs should be going wrong?

Time to add some debugging info to it and find out.  Is your ServletContextListener even being called?  Are you really running the configuration you think you are?  (IDEs tend to obfuscate the situation, which is why a lot of us will not attempt to run Tomcat under an IDE.)
 
> And I wonder if this may have anything to do with the Tomcat 
> out of memory messages I've been receiving?

Sounds like a separate topic for a separate thread.

 - Chuck 


THIS COMMUNICATION MAY CONTAIN CONFIDENTIAL AND/OR OTHERWISE PROPRIETARY MATERIAL and is thus for use only by the intended recipient. If you received this in error, please contact the sender and delete the e-mail and its attachments from all computers.




---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


RE: Tomcat memory leak error launching web app in NetBeans 6.9.1

Posted by "Caldarale, Charles R" <Ch...@unisys.com>.
> From: Martin O'Shea [mailto:appy74@dsl.pipex.com] 
> Subject: RE: Tomcat memory leak error launching web app in NetBeans 6.9.1

> I have NetBeans's Deploy on Save set. This seems to restart 
> the server with the current objects.

No, it restarts the webapp, not the server.

> But what I don't understand is why the ServletContextListener 
> which handles Quartz jobs should be going wrong?

Time to add some debugging info to it and find out.  Is your ServletContextListener even being called?  Are you really running the configuration you think you are?  (IDEs tend to obfuscate the situation, which is why a lot of us will not attempt to run Tomcat under an IDE.)
 
> And I wonder if this may have anything to do with the Tomcat 
> out of memory messages I've been receiving?

Sounds like a separate topic for a separate thread.

 - Chuck 


THIS COMMUNICATION MAY CONTAIN CONFIDENTIAL AND/OR OTHERWISE PROPRIETARY MATERIAL and is thus for use only by the intended recipient. If you received this in error, please contact the sender and delete the e-mail and its attachments from all computers.


RE: Tomcat memory leak error launching web app in NetBeans 6.9.1

Posted by Martin O'Shea <ap...@dsl.pipex.com>.
OK. So the error is happening as the application is closed, not as it started. My mistake. But Tomcat restarts occur frequently as I have NetBeans's Deploy on Save set. This seems to restart the server with the current objects.

But what I don't understand is why the ServletContextListener which handles Quartz jobs should be going wrong? It is set to start and stop Quartz at contextInitialized and contextDestroyed times where the former creates an instance of a SchedulerController class which submits the two jobs. 

This problem never appeared to happen under NetBeans 6.9 with an earlier version of Tomcat which I was using recently. 

And I wonder if this may have anything to do with the Tomcat out of memory messages I've been receiving? Do I need to increase the memory allocated to the JVM for Tomcat at all?

-----Original Message-----
From: Pid * [mailto:pid@pidster.com] 
Sent: 16 Oct 2010 15 06
To: Tomcat Users List
Subject: Re: Tomcat memory leak error launching web app in NetBeans 6.9.1

On 16 Oct 2010, at 12:45, Martin O'Shea <ap...@dsl.pipex.com> wrote:

> Hello
>
> I wonder if anyone can help here? I am developing a web application written
> in Java servlets and JSPs which uses Quartz 1.6.1 to submit two jobs when
> Apache Tomcat 6.0.26 is started and hourly after that.
>
> But what I'm finding is that a message is issued several times as the server
> is started in NetBeans 6.9.1. The message is:
>
> 16-Oct-2010 12:20:18 org.apache.catalina.loader.WebappClassLoader
> clearReferencesThreads
> SEVERE: A web application appears to have started a thread named
> [DefaultQuartzScheduler_Worker-1] but has failed to stop it. This is very
> likely to create a memory leak.

Yes. So, umm, your webapp uses quartz - which is starting threads and
not stopping them.

> Has anyone any idea? It seems to be causing Tomcat to stop every so often
> requiring a PC reboot. And I've found very little about this so far.

The error message is issued by Tomcat when an app is stopped and it
finds resources that haven't been properly terminated.

The message itself is doesn't cause a leak, the source of the problem
might - as the message itself states.

> I don't know if it is a problem with Tomcat or Quartz so any help is welcome

Quartz, or the way you've configured it.


p

>
>
> Thanks
>
> Martin O'Shea.
>
>
>

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org




---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Tomcat memory leak error launching web app in NetBeans 6.9.1

Posted by Pid * <pi...@pidster.com>.
On 16 Oct 2010, at 12:45, Martin O'Shea <ap...@dsl.pipex.com> wrote:

> Hello
>
> I wonder if anyone can help here? I am developing a web application written
> in Java servlets and JSPs which uses Quartz 1.6.1 to submit two jobs when
> Apache Tomcat 6.0.26 is started and hourly after that.
>
> But what I'm finding is that a message is issued several times as the server
> is started in NetBeans 6.9.1. The message is:
>
> 16-Oct-2010 12:20:18 org.apache.catalina.loader.WebappClassLoader
> clearReferencesThreads
> SEVERE: A web application appears to have started a thread named
> [DefaultQuartzScheduler_Worker-1] but has failed to stop it. This is very
> likely to create a memory leak.

Yes. So, umm, your webapp uses quartz - which is starting threads and
not stopping them.

> Has anyone any idea? It seems to be causing Tomcat to stop every so often
> requiring a PC reboot. And I've found very little about this so far.

The error message is issued by Tomcat when an app is stopped and it
finds resources that haven't been properly terminated.

The message itself is doesn't cause a leak, the source of the problem
might - as the message itself states.

> I don't know if it is a problem with Tomcat or Quartz so any help is welcome

Quartz, or the way you've configured it.


p

>
>
> Thanks
>
> Martin O'Shea.
>
>
>

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org