Tomcat hangs when shutting down (daemon) threads (ScheduledExecutorService) - java

In my webapp i have classes that used to extend thread class with a run() routine. I had problems with them when shutting down tomcat so replaced the thread implementations with a ScheduledExecutorService.
However it still does not work: When shutting down tomcat in my eclipse console there are logging statements like this:
org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads The web application [Appname] appears to have started a thread named [Timer-1] but has failed to stop it. This is very likely to create a memory leak.
After a timeout i always get a message, that tomcat is not responding and i have to terminate it manually.
I am starting those in an init() and destroy() method of my servlet like this:
public void init() throws ServletException
{
worker = new worker();
worker.schedule();
}
public void destroy()
{
worker.shutdownTimer();
worker = null;
}
The methods look like this:
private ScheduledExecutorService mScheduler = null;
public void schedule()
{
scheduler = getScheduleService();
scheduler.scheduleAtFixedRate(new Runnable()
{
public void run()
{
//...things to do in the routine
}
},
1, //start after 1 second
10, //wait 10 seconds
TimeUnit.SECONDS);
}
private ScheduledExecutorService getScheduleService()
{
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1, new ThreadFactory()
{
public Thread newThread(Runnable r)
{
Thread thread = new Thread(r);
// allow the JVM to kill the scheduled task
thread.setDaemon(true);
return thread;
}
});
return scheduler;
}
public void shutdownTimer()
{
if (scheduler != null)
scheduler.shutdownNow();
}
In my debugger i can see that the executorservice has started following thread:
Daemon Thread [Timer-0] Running
Thread [pool-3-thread-1] Running
Why does the ExecutorService start a normal threadpool?
And when does the jvm still have problem closing those threads when i'm explicitly telling it to shut them down in my servlet?

Related

ScheduledExecutorService and Shutdown Hook

When I use a ScheduledExecutorService (or ExecutorService) and submit a Runnable, my shutdown hook never gets called. Ex, this program hangs:
public class App {
static ScheduledExecutorService exec = Executors.newSingleThreadScheduledExecutor();
static {
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
exec.shutdownNow();
}
});
}
public static void main(String[] args) {
exec.schedule(new Runnable() {
#Override
public void run() {
}
}, 10, TimeUnit.SECONDS);
}
}
Since the executor's thread is not a daemon, I would expect the shutdown hook to be called, but it's not. Any idea why?
From the javadoc of Runtime#addShutdownHook(Thread):
The Java virtual machine shuts down in response to two kinds of
events:
The program exits normally, when the last non-daemon thread exits or when the exit (equivalently, System.exit) method is invoked, or
The virtual machine is terminated in response to a user interrupt, such as typing ^C, or a system-wide event, such as user logoff or
system shutdown.*
As you said yourself, the threads in the Executor returned by newSingleThreadScheduledExecutor are not daemon threads. So they must exit before your shutdown hook can be invoked.
You're doing things backwards. You need to shutdown your Executor from some other part of your program's execution, not the shutdown hook. The shutdown hook will run after the Executor has terminated.
* Assuming you aren't trying to send a user interrupt to your java process.
In the event you absolutely need to shutdown the executor after the task has run you can implement something like this:
static {
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
Logger.getGlobal().info("destroying");
exec.shutdownNow();
}
});
}
public static void main(String[] args) throws Exception {
Future f = exec.schedule(new Runnable() {
#Override
public void run() {
Logger.getGlobal().info("thread run");
}
}, 10, TimeUnit.SECONDS);
while (!f.isDone()) {
Logger.getGlobal().info("waiting for task to finish");
Thread.sleep(1000);
}
Runtime.getRuntime().exit(0);
}

ScheduledExecutorService - program not ending after one-shot action

I have a scheduled task in my program that closes a frame after a given period of time. However, after the task has been executed, the program keeps running as if the ScheduledExecutorService was still running on a different thread.
This is the relevant part of my code:
int delay = 1000;
ScheduledExecutorService ex = Executors.newSingleThreadScheduledExecutor();
ex.schedule(() -> {
System.out.println("executed");
getWindow().closeWindow();
// ex.shutdown();
}, delay, TimeUnit.MILLISECONDS);
Here the task is executed after a 1 second delay, "executed" is printed once, the frame closes, and the program keeps running even after this code. If I uncomment the ex.shutdownNow();, the program successfully ends as intended. However, I cannot figure out why this is happening. I also failed to find anything from the rest of the Internet.
MCVE:
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class Main {
public static void main(String[] args) {
int delay = 1000;
ScheduledExecutorService ex = Executors.newSingleThreadScheduledExecutor();
ex.schedule(() -> {
System.out.println("executed");
// ex.shutdown();
}, delay, TimeUnit.MILLISECONDS);
}
}
The lambdas might've given it away, but this is indeed Java 8.
Why is the program not stopping after the task has been executed?
The ScheduledExecutorService thread pool returned by Executors#newSingleThreadScheduledExecutor() uses non daemon threads. Until you shut down the thread pool, these are still alive awaiting tasks. A JVM does not end while non-daemon threads are alive.
You can use the overloaded Executors#newSingleThreadScheduledExecutor(ThreadFactory) and provide your own ThreadFactory implementation which creates daemon threads. Note that this risks the case where your task may not even run because the JVM would exit before the task's scheduled time.
Do as you've discovered and shut it down. Note that you should shut always it down somewhere safe, where the operation can't fail.
The Java Virtual Machine runs until all threads that are not daemon threads have died. And Executors.defaultThreadFactory() creates each new thread as a non-daemon thread. However, there is an overload of Executors.newSingleThreadScheduledExecutor(); which takes a ThreadFactory as a parameter, if you care to venture in that direction.
public static void main(String[] args) {
int delay = 1000;
class DaemonFactory implements ThreadFactory
{
#Override
public Thread newThread(Runnable r)
{
Thread t = new Thread(r);
t.setDaemon(true);
return t;
}
}
ThreadFactory tf = new DaemonFactory();
ScheduledExecutorService ex = Executors.newSingleThreadScheduledExecutor(tf);
ex.schedule(() -> {
System.out.println("executed");
}, delay, TimeUnit.MILLISECONDS);
}
I would approach this entirely differently. You state:
I have a scheduled task in my program that closes a frame after a given period of time.
Why not instead use a Swing Timer for this as this was built to work well with the Swing event thread?
new Timer(1000, new ActionListener() {
public void actionPerformed(ActionEvent e) {
((Timer) e.getSource()).stop();
someWindow.dispose();
}
}).start();
You can call shutdown from ScheduledExecutorService as it will wait for thread execution and then finalize thread pool. As you can see in Javadoc: "Initiates an orderly shutdown in which previously submitted tasks are executed, but no new tasks will
be accepted. Invocation has no additional effect if already shut down."
Example:
...
scheduledExecutorService.schedule(runnable, delay, TimeUnit.MILLISECONDS);
scheduledExecutorService.shutdown();
...
I am starting scheduler from onCreate() and stopping it in onDestroy() approach to stop the scheduler service.
public MyActivity extends Activity
{
ScheduledExecutorService scheduledExecutorService;
ScheduledFuture<?> scheduledFuture;
private int apiThreshold = 10;//seconds
onCreate()
{
startScheduler();
}
onDestroy()
{
if (scheduledFuture != null)
{
stopScheduler();
}
shutDownService();
super.onDestroy();
}
public void startScheduler() {
Debug.e(TAG, "inside start scheduler");
scheduledExecutorService = Executors.newScheduledThreadPool(1);
scheduledFuture = scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
#Override
public void run() {
// call method to do your task/perform your repeated task
}
}, 4, apiThreshold, TimeUnit.SECONDS);
}
public void shutDownService()
{
if (scheduledExecutorService != null) {
Log.e(“test,"in shutDown service close if not null");
scheduledExecutorService.shutdownNow(); // shutdown will allow the final iteration to finish
// executing where shutdownNow() will kill it immediately
Log.e(“test,"is service shutdown(true/false)=="+scheduledExecutorService.isShutdown());
}
}
}

Daemon Thread prevents JVM from terminating - possible reasons?

I need to develop a maven plugin that can start an apache ftp-server, run it as a daemon (does not halt the build process) and stop it as another goal. Unfortunately my first attempt to with daemon threads fails:
public class FtpServerDaemon
{
public static void main(final String[] args) throws Exception
{
Thread thread = new Thread(new Runnable()
{
#Override public void run()
{
org.apache.ftpserver.main.Daemon.main(args);
}
});
thread.setDaemon(true);
thread.start();
Thread.sleep(10000);
}
}
The bad thing here is that the JVM does not terminate after 10 seconds but it runs indefinitely. If the Daemon.main is a black-box code (however the source is available), what can prevent the JVM from terminating in a daemon thread?
Agree with assylias and chrylis comments.
Instead of org.apache.ftpserver.main.Daemon.main(args); can you try some other code there? A loop that lasts more than the time the main thread sleeps should do, printing a number every n seconds or something.
I believe it must then terminate properly. Just to test whether the ftpserver is preventing the exit.
By the way, if a Daemon thread spawns a child thread, the child threads are automatically set as Daemon, right? So why this might be happening?
The FtpServer starts non-daemon threads and they are still running. If a thread is spawned from a daemon thread, the new thread will initially inherit the daemon status from its parent, but one can override it. E.g.:
Thread thread = new Thread(new Runnable()
{
#Override public void run()
{
Thread embeddedNonDaemon = new Thread(new Runnable()
{
#Override public void run()
{
while (true)
{
;
}
}
});
embeddedNonDaemon.setDaemon(false);
embeddedNonDaemon.start();
}
});
thread.setDaemon(true);
thread.start();
Thread.sleep(5000);
This code does not terminate, either.

Shutdown hook is not killing executor

I have the following code:
public class Driver {
private ExecutorService executor = Executors.newCachedThreadPool();
public static void main(String[] args) {
Driver d = new Driver();
d.run();
}
private void run() {
final Timer timer = new Timer();
final TimerTask task = new TimerTask() {
#Override
public void run() {
System.out.println("Task is running!");
}
};
Runnable worker = new Runnable() {
#Override
public void run() {
timer.scheduleAtFixedRate(task, new Date(), 5 * 1000);
}
};
Runtime.getRuntime().addShutdownHook(new Thread() {
#Override
public void run() {
System.out.println("Shutdown hook is being invoked!");
try {
if(executor.awaitTermination(20, TimeUnit.SECONDS))
System.out.println("All workers shutdown properly.");
else {
System.out.println(String.format("Maximum time limit of %s reached " +
"when trying to shut down workers. Forcing shutdown.", 20));
executor.shutdownNow();
}
} catch (InterruptedException interrupt) {
System.out.println("Shutdown hook interrupted by exception: " +
interrupt.getMessage());
}
System.out.println("Shutdown hook is finished!");
}
});
executor.submit(worker);
System.out.println("Initializing shutdown...");
}
}
When this runs I get the following console output:
Initializing shutdown...
Task is running!
Task is running!
Task is running!
Task is running!
Task is running!
Task is running!
Task is running!
... (this keeps going non-stop)
When I run this, the application never terminates. Instead, every 5 seconds, I see a new println of "Task is running!". I would have expected the main thread to reach the end of the main method, print "Initializing shutdown...", invoked the added shutdown hook, killed the executor, and finally print out "Shutdown hook is finished!".
Instead, "Task is running" just keeps getting printed and the program never terminates. What's going on here?
I am no expert but AFAIK you must have all non-Daemon threads terminated in order for the shutdown hook to “kick in”.
In the original example you have 3 non-Daemon:
The thread of “Main” – this is the only non-Daemon you want here..
The thread that runs the “TimerTask” – it is created by the “Timer” and you covered it by fixing to Timer(true)
The thread that runs the “worker” – it is created by the “executor” and in order for the “executor” to create Daemon threads you should create a ThreadFactory. (at least this is the way I know; there might be other ways...)
So I think what you should do is to create a ThreadFactory and use it when initializing the “executor”.
Create a class that will be the ThreadFactory:
private class WorkerThreadFactory implements ThreadFactory {
#Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r, "Worker");
t.setDaemon(true);
return t;
}
}
-- the important line is the setDaemon of course :)
Pass an instance of it as a parameter to the newCachedThreadPool method:
private ExecutorService executor = Executors.newCachedThreadPool(new WorkerThreadFactory());
Applying these 2 changes did the trick for me and I got to:
Maximum time limit of 20 reached when trying to shut down workers. Forcing shutdown.
Shutdown hook is finished!
Hope it helps,
Izik
golan2#hotmail.com
It is not shutting down because Timer() creates and starts a non-daemon thread ... which is then never stopped.
There are two things that can cause the JVM to shutdown of its own accord:
A call to System.exit() (or Runtime.halt())
The termination of the last remaining non-daemon thread.
Since you have created a second non-daemon thread (in addition to the thread that is running main()) the second condition won't be met.

Java webapp memory leak when using ScheduledExecutorService

My Tomcat 7 is reporting that there may be a memory leak in my webapp
SEVERE: The web application [/mywebapp] appears to have started a
thread named [pool-1-thread-1] but has failed to stop it. This is
very likely to create a memory leak.
I have a long running task in my webapp that gets initialized when the webapp is started.
public class MyContextListener implements ServletContextListener{
Scheduler scheduler = null;
public MyContextListener(){
scheduler = new Scheduler();
}
#Override
public void contextDestroyed(ServletContextEvent arg0) {
scheduler.stop();
}
#Override
public void contextInitialized(ServletContextEvent arg0) {
scheduler.start();
}
}
.. and my Scheduler.java
public class Scheduler {
private final ScheduledExecutorService fScheduler;
public Scheduler() {
fScheduler = Executors.newScheduledThreadPool(1);
}
public void start(){
fScheduler.scheduleWithFixedDelay(new Runnable() {
#Override
public void run() {
//Perform some task
}
}, 1, 240, TimeUnit.MINUTES);
}
public void stop(){
fScheduler.shutdownNow();
}
}
Even though I calling scheduler.stop(); when shutting down the server, its still reporting there could be a memory leak.
This app is deployed on jelastic.com and I find that once it is started, it runs well for around two days and then the tasks don't seem to be running. There is no exceptions or errors in the logs too.
Am I doing anything wrong here ? Is there really a potential memory leak ?
Calling fScheduler.shutdownNow(); is not enough:
There are no guarantees beyond best-effort attempts to stop processing actively executing tasks.
From JavaDoc.
Instead you must explicitly wait for the tasks that are currently running:
fScheduler.shutdownNow();
fScheduler.awaitTermination(10, TimeUnit.SECONDS);
I believe you should not call the shutdown from the Listener but from the Servlet directly.
contextDestroyed() of the listener is too late for the executor service. As stated in the javadoc All servlets and filters will have been destroyed before any ServletContextListeners are notified of context destruction.
whereas overriding the servlet destroy() should be OK as according to the javadoc This method gives the servlet an opportunity to clean up any resources that are being held (for example, memory, file handles, threads...
#Override
public void destroy( ) {
fScheduler.shutdownNow();
fScheduler.awaitTermination(10, TimeUnit.SECONDS);
super.destroy( );
}

Categories

Resources