I'm trying to use log4j2 in a tomcat based web application, so I added log4j web module along with other essential jars. However when stopping this web application I'm getting the following exception.
FATAL Unable to register shutdown hook because JVM is shutting down
Why I'm getting this error and what I can do to prevent this error ?
Thanks!
As explained in Pouriya's answer, you are probably trying to use the Log4j2 when your application is already stopping without a proper shutdown hook. Since you are talking about a Tomcat web application, I assume you are using Servlets. (If you don't, see the second part below). Then, you must declare this in your ContextListener:
public class ContextListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent evt) {
String appenderName = evt.getServletContext().getInitParameter("log4jContextName");
File file = new File(evt.getServletContext().getInitParameter("log4jConfiguration"));
if(!file.exists()){
logger = LogManager.getRootLogger();
} else{
logger = LogManager.getLogger(appenderName);
}
}
}
@Override
public void contextDestroyed(ServletContextEvent evt) {
// You don't really need to do anything here, about the logger.
// The log4j2 JAR will handle it properly.
}
As usual with web applications, the Log4J2's config file must be indicated in the web.xml file, as:
<?xml version="1.0" encoding="UTF-8"?>
<web-app ... >
<context-param>
<param-name>log4jContextName</param-name>
<param-value>myApplication</param-value>
</context-param>
<context-param>
<param-name>log4jConfiguration</param-name>
<param-value>/the/path/to/your/log4j.properties.file</param-value>
</context-param>
</web-app>
If you are instead using a normal application, then you need to add explicitly your shutdown hook:
public static void main( String[] args ) {
...
File file = new File(logFileName);
if(!file.exists()){
logger = LogManager.getRootLogger();
} else {
System.setProperty("log4j.configurationFile", file.toURI().toURL().toString());
logger = LogManager.getLogger("yourProgramName");
}
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
logger.info("Shutting down - closing application");
// Shut down everything (e.g. threads) that you need to.
// then shut down log4j
if( LogManager.getContext() instanceof LoggerContext ) {
logger.debug("Shutting down log4j2");
Configurator.shutdown((LoggerContext)LogManager.getContext());
} else
logger.warn("Unable to shutdown log4j2");
// logger not usable anymore
System.out.println("Done.");
}
});
}
The shutdown hook will be called when your application is ended (i.e. when calling System.exit(0)
.
You also need to add this in your Log4J2 config file:
XML version:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration shutdownHook="disable">
...
</Configuration>
Json version:
{"configuration":
{
"shutdownHook":"disable",
....
}
}
This will tell Log4j2 that you're handling the shutdown of the Logger yourself.
(Since in a normal application you don't have a web.xml file, you have to retrieve your configuration file in some other way).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With