Java -How to get logger to work in shutdown hook? - java

I have a specialized logger class which uses the java.util.logging.Logger class. I want to be able to use this logger in the shutdown hook of another class. However, it doesn't seem to log at shutdown. From what I've read, there may already be a shutdown hook activated for the logger itself which is causing the issue.
How can I get this to work? Ideally, I would like it to be seen in the log file that I did in fact execute the shutdown hook when the process terminated.

Again looking at the source, the solution appears to be to define a system property java.util.logging.manager which is a subclass of LogManager which overrides the reset(); method so the Loggers continue to work on shutdown.
import java.util.logging.LogManager;
import java.util.logging.Logger;
public class Main {
static {
// must be called before any Logger method is used.
System.setProperty("java.util.logging.manager", MyLogManager.class.getName());
}
public static class MyLogManager extends LogManager {
static MyLogManager instance;
public MyLogManager() { instance = this; }
#Override public void reset() { /* don't reset yet. */ }
private void reset0() { super.reset(); }
public static void resetFinally() { instance.reset0(); }
}
public static void main(String... args) {
Logger logger1 = Logger.getLogger("Main1");
logger1.info("Before shutdown");
Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
#Override
public void run() {
try {
Logger logger2 = Logger.getLogger("Main2");
logger2.info("Shutting down 2");
} finally {
MyLogManager.resetFinally();
}
}
}));
}
}
prints
Dec 11, 2012 5:56:55 PM Main main
INFO: Before shutdown
Dec 11, 2012 5:56:55 PM Main$1 run
INFO: Shutting down 2
From this code for LogManager, you can see see there is a shutdown hook which dismantles the handlers and closes them. Logger only works in shutdown if it hasn't been used before so this code is not run.
// This private class is used as a shutdown hook.
// It does a "reset" to close all open handlers.
private class Cleaner extends Thread {
private Cleaner() {
/* Set context class loader to null in order to avoid
* keeping a strong reference to an application classloader.
*/
this.setContextClassLoader(null);
}
public void run() {
// This is to ensure the LogManager.<clinit> is completed
// before synchronized block. Otherwise deadlocks are possible.
LogManager mgr = manager;
// If the global handlers haven't been initialized yet, we
// don't want to initialize them just so we can close them!
synchronized (LogManager.this) {
// Note that death is imminent.
deathImminent = true;
initializedGlobalHandlers = true;
}
// Do a reset to close all active handlers.
reset();
}
}
/**
* Protected constructor. This is protected so that container applications
* (such as J2EE containers) can subclass the object. It is non-public as
* it is intended that there only be one LogManager object, whose value is
* retrieved by calling Logmanager.getLogManager.
*/
protected LogManager() {
// Add a shutdown hook to close the global handlers.
try {
Runtime.getRuntime().addShutdownHook(new Cleaner());
} catch (IllegalStateException e) {
// If the VM is already shutting down,
// We do not need to register shutdownHook.
}
}
From my own testing
Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
#Override
public void run() {
try {
Logger logger2 = Logger.getLogger("Main2");
logger2.info("Shutting down 2");
} catch (Throwable t) {
t.printStackTrace();
}
}
}));
prints
Dec 11, 2012 5:40:15 PM Main$1 run
INFO: Shutting down 2
but if you add
Logger logger1 = Logger.getLogger("Main1");
outside this block you get nothing.

Does the shutdown hook has any advantage?
You better, add the Log output in the last line in main:
The finally block will be executed in all cases,
except when the VM crashes but then the shutdown hook will
not be executed, too.
static void main(String[] argv) {
try {
startApp();
} finally {
LOGGER.info("shudown");
}
}

Related

Unable to execute task using ExecutorService in static workflow/block

I am working on a module where a one-time cache is loaded using the static workflow. Cache loading usually takes around an hour. To improve the performance I am thinking about running these tasks in parallel using a thread pool. Here is the sample code.
Application Startup class:
public class AppStart {
public static void main(String[] args) {
Cache.isValid(); // this will trigger the static workflow
// ...
}
}
Cache loader class:
public class Cache {
static {
System.out.println("Static block initialization started!");
initialize();
System.out.println("Static block initialization finished!");
}
public static void initialize( ) {
System.out.println("initialize() started!");
ExecutorService executorService = Executors.newSingleThreadExecutor(); // will replace with fixedThreadPool
Future<String> future = executorService.submit(() -> "Hello world!");
System.out.println("Retrieve the result of the future");
String result = null;
try {
result = future.get();
System.out.println(result);
} catch( InterruptedException e ) {
e.printStackTrace();
} catch( ExecutionException e ) {
e.printStackTrace();
}
executorService.shutdown();
}
public static boolean isValid( ) {
return true;
}
}
However, in the above case blocking operation future.get is getting blocked forever, even though it does nothing but a trivial task to return a String.
I also tried using ForkJoinPool, I had no luck.
I monitored threads using jconsole could not detect any deadlock. why is it behaving weirdly?
The static initializer for your Cache class doesn't complete – it's waiting on the completion of future.get(). You could remove the static initializer and call your method directly – Cache.initialize() – from main() or somewhere else, but whatever thread does that is going to be similarly blocked.
I suggest you create a separate thread to call initialize(), thus avoiding the blocking behavior, like this:
new Runnable() {
#Override
public void run() {
initialize();
}
}.run();
This seems to be the expected behavior. this is a classic class initialization deadlock.
a new Thread is started using the Runnable that is dependent on the completion of static initialization of a class. The class is, in turn, waiting for the Runnable to finish because of the future.get() method call.
The static initialization is waiting for thread to complete and thread is waiting for static initialization to complete.
JLS:: Class initialiization gives details on the class initialization process.
I wonder why jconsole couldn't detect the deadlock

How to close Spring beans properly after received a SIGTERM?

I'm trying to keep my application alive in order to listen for some messages from my queue. However, once my application receives a SIGTERM, I would like to ensure that my application shutdown nicely. Meaning, ensure that the jobs, internally, has finished first, before the shutdown.
After reading about it , I came up with this:
#Component
public class ParserListenerStarter {
public static void main(final String[] args) throws InterruptedException {
ConfigurableApplicationContext context = new AnnotationConfigApplicationContext(ParserReceiveJmsContext.class);
context.registerShutdownHook();
System.out.println("Listening...");
Runtime.getRuntime().addShutdownHook( //
new Thread() {
#Override
public void run() {
System.out.println("Closing parser listener gracefully!");
context.close();
}
});
while (true) {
Thread.sleep(1000);
}
}
}
Then I send a kill command to my application; and this is my output:
Listening...
// output from my other beans here
Closing parser listener gracefully!
Process finished with exit code 143 (interrupted by signal 15: SIGTERM)
The shutdown methods from my beans were not called:
#PreDestroy public void shutdown() {..}
I'm not an expert in Spring, so I'm sorry for any silly point that I'm missing here.
How can I shutdown my beans and then close my application nicely ?
All you need:
context.registerShutdownHook();
So, add the code above and then your #PreDestroy method will be invoked.
After that you don't need to do anything else. It means you must can delete
Runtime.getRuntime().addShutdownHook( //
new Thread() {
#Override
public void run() {
System.out.println("Closing parser listener gracefully!");
context.close();
}
});
EDIT:
Documentation says that you can have multiple shutdown hooks:
When the virtual machine begins its shutdown sequence it will start all registered shutdown hooks
So the statement below is incorrect:
When you added this, you replaced the Spring hook, which do the beans destroying, because internally, method looks like
if (this.shutdownHook == null) {
// No shutdown hook registered yet.
this.shutdownHook = new Thread() {
#Override
public void run() {
doClose();
}
};
Runtime.getRuntime().addShutdownHook(this.shutdownHook);
}

Exceptions silently swallowed in play framework

I encountered a problem with logging exceptions using play framework.
Suppose, we have some runnable class RunnableClass, that can be initialized in Global class and can be executed in Executor service.
public class Global extends GlobalSettings {
#Override
public void beforeStart(Application app) {
Runnable runnableClass = new RunnableClass();
runnableClass.setSmth(new Smth());
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(10);
scheduledExecutorService.scheduleAtFixedRate(runnableClass, 0, 1, TimeUnit.MINUTES);
}
}
Suppose, we need to operate with Smth class in run() method of RunnableClass.
private class RunnableClass implements Runnable {
private Smth smth;
public void setSmth(Smth smth) {
this.smth = smth;
}
#Override
public void run() {
smth.doSomething();
}
}
But for some reason we will not get here NullPointerExcception or any else exception. Obviously, that stack trace of this exception will be logged at least to console, but i see nothing either in console, nor in application.log file.
My version of play - 2.2.1, sbt launcher version - 0.13.0, application.conf file - default.
I tried next link:
http://www.playframework.com/documentation/2.0.x/SettingsLogger

ScheduledExecutorService doesn't works during my junit test

I am working on writing some junit test for my spring application. Below is my junit test that that calls afterPropertiesSet method of my InitializeFramework class that implements InitializingBean interface.
Below is the flow where my junit test calls afterPropertiesSet method and then that method will call initializeModel method within the same class, and then that method has a scheduler which will call getBundlesInfo method every few minutes. But somehow during my junit, getBundlesInfo method is not getting called at all.
#Test
public void testFramework() {
try {
InitializeFramework io = new InitializeFramework();
io.afterPropertiesSet();
} catch (Exception e) {
}
}
public class InitializeFramework implements InitializingBean {
private static long checkWithDBInterval = 1L;
private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
#Override
public void afterPropertiesSet() throws Exception {
try {
// other code here
initializeModel();
} catch (Exception e) {
}
}
private void initializeModel() {
final ScheduledFuture<?> taskHandle = scheduler.scheduleAtFixedRate(
new Runnable() {
public void run() {
try {
getBundlesInfo();
} catch(Exception ex) {
// log exception here
}
}
}, 0, checkWithDBInterval, TimeUnit.MINUTES);
}
// this method is not getting called from my junit test
protected static void getBundlesInfo() {
// some code here
// have put the breakpoint here..
}
}
Can anybody help me with this? What wrong I am doing here? but during my application run, this flow works perfectly fine and getBundlesInfo gets called... Only during junit it is not working..
This happens because your unit test exits before the scheduler executes your Runnable.
Do you want to test that afterPropertiesSet calls getBundlesInfo or do you want to test the repeated invocation of getBundlesInfo?
How does your unit test assert that getBundlesInfo got called? Or are you not there yet?
If you just want to see that getBundlesInfo is called, you either could make a direct call to it and increase the initialDelay of your scheduler to checkWithDBInterval, or stub getBundlesInfo with Mockito and/or Powermock to for example use a CountDownLatch to synchronize on.
Well or just wait a couple of seconds after the call to afterPropertiesSet and then check if getBundlesInfo was called (which you can do with Mockito also btw).
In any case, you might want to add code which calls shutdown on the executor service after the test is finished
Since you use Spring:
Consider using the provided Task Execution and Scheduling framework to schedule the repeated call to getBundlesInfo and having afterPropertiesSet directly call getBundlesInfo initially.
Anyway, here is an example with stubbing and using a CountDownLatch for the waiting part.
I also had to make getBundlesInfo non-static, as i couldnt quickly remember/find how to stub a static method.
import static org.mockito.Mockito.*;
import java.util.concurrent.*;
import org.junit.Test;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
public class StackOverflowTest
{
public static class ClassWithScheduler
{
private static long checkWithDBInterval = 1L;
private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool( 1 );
public void entryPoint()
{
scheduler.scheduleAtFixedRate( new Runnable() {
public void run()
{
try
{
thisHasToBeCalled();
}
catch( Exception ex )
{
// log exception here
}
}
}, 0, checkWithDBInterval, TimeUnit.MINUTES );
}
protected void thisHasToBeCalled()
{
System.out.println( "thisHasToBeCalled was called" );
}
}
// since we are waiting on another thread either use a timed-wait (latch.await also
// has a variant which accepts a timeout) or use the timeout attribute of the
// #Test annotation
#Test( timeout = 5000L )
public void testCall() throws Exception
{
// create latch which this thread waits on and the scheduler thread
// notifies on
final CountDownLatch latch = new CountDownLatch( 1 );
// create instance
ClassWithScheduler instance = spy( new ClassWithScheduler() );
// stub thisHasToBeCalled to notify on the latch
doAnswer( new Answer<Void>() {
#Override
public Void answer( InvocationOnMock invocation ) throws Throwable
{
// call the real method
invocation.callRealMethod();
// notify waiting thread
latch.countDown();
System.out.println( "stub" );
return null;
}
} ).when( instance ).thisHasToBeCalled();
// execute
instance.entryPoint();
// wait for thread to call the stubbed method
latch.await();
// assert that the method was called /
verify( instance ).thisHasToBeCalled();
}
}
You will notice that if you change your getBundlesInfo() to something like
protected static void getBundlesInfo() {
System.out.println("ay");
}
and the TimeUnit you are using to TimeUnit.MILLISECONDS, that it will print as much as it can. For example, I got
ay
ay
ay
ay
This is because JUnit cleans up any threads running on the JVM before exiting. It kills/stops/interrupts them.

Tomcat fails to stop thread in webapp

In my webapp I have 3 threads where tomcat fails to stop 2 of these on reload.
SEVERE: The web application [/myapp] appears to have started a thread named [Thread-8] but has failed to stop it. This is very likely to create a memory leak.
mai 08, 2013 11:22:40 AM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
This causes the CPU usage to rise for each reload.
Here is one of the threads that tomcat fails to stop:
Some of the code implemented in my ServletContextListener:
public void contextInitialized(ServletContextEvent event)
{
final UpdaterThread updaterThread = new UpdaterThread();
updaterThread.start();
event.getServletContext().setAttribute("updaterthread", updaterThread);
}
public void contextDestroyed(ServletContextEvent event)
{
UpdaterThread updaterThread = (UpdaterThread) event.getServletContext().getAttribute("updaterthread");
if (updaterThread != null)
{
updaterThread.stopUpdater();
updaterThread.interrupt();
updaterThread = null;
}
}
And the important parts of UpdaterThread:
public class UpdaterThread extends Thread implements Runnable
{
private boolean alive = true;
#Override
public void run()
{
while(true)
{
try
{
while (alive)
{
doUpdate();
sleep(60*1000);
}
}
catch (InterruptedException ie) {}
catch (Exception e) {}
}
}
public void stopUpdater()
{
alive = false;
}
}
Does anyone have any idea why this thread don't stops? Is there a better way to implement a thread doing some work at specific times?
As far as I can see, you're not actually stopping your thread at all. You have two while loops, and you only stop the inner when you set alive = false. The outer will run forever, doing nothing. You also don't handle the interrupt your sending, so that won't terminate the thread either.
I would instead do something like this:
public void run()
{
while(alive)
{
try
{
doUpdate();
sleep(60*1000);
}
catch (InterruptedException ie) {
alive = false;
}
}
}
Also, if you give your thread a proper name when creating it, you'll see if it's actually that thread that is causing the problem Tomcat is reporting.
it’s related to ThreadLocal issues with tomcat, Check this document
http://wiki.apache.org/tomcat/MemoryLeakProtection
Mar 16, 2010 11:47:24 PM org.apache.catalina.loader.WebappClassLoader
clearThreadLocalMap SEVERE: A web application created a ThreadLocal
with key of type [test.MyThreadLocal] (value
[test.MyThreadLocal#4dbb9a58]) and a value of type [test.MyCounter]
(value [test.MyCounter#57922f46]) but failed to remove it when the web
application was stopped. To prevent a memory leak, the ThreadLocal has
been forcibly removed.
http://forum.springsource.org/showthread.php?84202-Installation-ThreadLocal-forcefully-removed
A Small change in your code to fix this issue
public class UpdaterThread extends Thread implements Runnable
{
private boolean alive = true;
#Override
public void run()
{
while(alive)
{
try
{
doUpdate();
sleep(60*1000);
}
catch (InterruptedException ie) {
//sleep interrupted
}
catch (Exception e) {
// exception in doUpdate method ? must handle this
}
}
}
public void stopUpdater()
{
alive = false;
}
}
However, Sleep in while loop likely to create a performance issue. You could use Thread.sleep only if you want to suspend your thread for some time. Do not use it if you want to wait for some condition.
Check this SO question : Thread-sleep-called-in-loop

Categories