Don't use System.exit() on Java Web Application

I have recently come across a code snippet, where programmer was using System.exit() if application failed to acquire necessary resource after couple of retry. His reasoning was that since, application cannot function, if essential resources like database is not available or there is no disk space to write records in File system. Ok, I hear you; but System.exit() in Java Web application, which runs inside either web server or application server, which itself is Java program is not a good idea at all. Why? because invoking System.exit() kills your JVM, invoking this from Tomcat or Jetty, will not only kill your application but most likely server itself. This can be potentially dangerous, if that server also host other critical application, which is not uncommon at all. As per my experience, System.exit() calls are quite common in overly broad try-catch blocks in web application start-up code that loads environment variables, properties files, connect to MQ Series, establishes database connection, opens socket connections, etc. This is still ok, if you are writing core Java based server, where each application has their own JVM, but with web application deployed on Tomcat, JBoss, WebSphere, Weblogic or any other application server, using System.exit() is big mistake. In worst case can result in outage for lots of other critical application. On the other hand, there are ways to prevent your web application from someone else’s mistake, by enabling Security Manager. System.exit() and Runtime.exit() both goes through the security manager. Enabling Security manager will catch these calls and reduce them into an exception rather than shutting down the whole VM. It's not difficult to enable the security manager in most application servers, Tomcat, JBoss both has documented steps to enable security Manager.



Why you should not use System.exit() in Java Web application

I think it's well known for senior Java developer that System.exit() shouldn't be used except in e.g. command-line tools; Many beginner Java programmers, though familiar with System.exit(), may not know that using them in a Servlet/JSP code can result in shutdown of server itself, so if you have of any of them in your team them take some time to educate them about coding in Java web application. In fact coding a Java based web application is totally different then coding a core Java application e.g. core concerns like threading, object pooling, parsing are all done by Web server and it's prohibited for application code to create threads. In fact use of ThreadLocal variable can create memory leak in Java web-app, so coding in web-app require more caution than in core Java application. By the way there are other reasons, why using System.exit is absolutely terrible. Especially when you dealing with un-managed resources, if you don't release resources properly and hope that OS will do the clean-up for you, then it could lead to a temporary resource leak, until OS really clean stuff created by your Java application.

Using System.exit() in Java Web Application


What does this all mean? Do System.exit() has any legitimate use? Of course there are many cases where use of System.exit is imperative. Sometime you really want to close your JVM once done, especially if it spawned from scheduling software like Control-M or Autosys. For example command line Java applications and scheduled tasks, can use System.exit(). Ideally, if you are sure that calling System.exit() will not have any side effect, you can use it. Here is a sample use of system.exit() in core Java application :

public static void main( String[] args ){

    try
    {
        processFxRatesFileAndPutIntoDatabase();

    }  catch ( Exception e )
    {
        logError(e);
        // if you need to exit with a failed status then System.exit(statusCode) is fine here.
        // otherwise program will complete successfully, once it return from main() method
    }

 }

Remember, if you are using Java program as command line tool then you can return System.exit(0) or System.exit(1) as whether it succeeded or failed. A non-zero exit status code, usually indicates abnormal termination. You can return different error codes to indicate different errors e.g. bad arguments, can't find file, could not connect to database etc. I hope you notice difference between using System.exit(1) and letting the Java program complete successfully. When java platform will terminate with System.exit() it will do so with a non-zero status (as long as the main thread ends and there are no running daemon threads).


That’s all about Why you should not use System.exit() inside Java application. It can be dangerous and potentially shutdown whole server, which is hosting other critical Java application. For example if you have more than one application in tomcat and one of them call System.exit() then whole tomcat will be shutdown and all other web application will also be shutdown. As a safety net or Insurance, you must enable Security Manager of your Server. It catches a lot of security problems! Including intentional and unintentional call to System.exit() or Runtime.exit(), turning it into an exception rather than shutting down the whole JVM. You are relatively safe to use System.exit() in command line Java application, as they run on their own JVM and can be used to signal a success and failure by returning different status code in case of failure.


5 comments :

SARAL SAXENA said...

@Javin ..well still I can see and people ask lots of questions in case of web application with respect to servlet specially..that..

Is calling System.exit() inside a Servlet's destroy() method to forcefully kill any non-daemon threads a good idea?

Calling System.exit() inside ANY servlet-related method is always 100% incorrect. Your code is not the only code running in the JVM - even if you are the only servlet running (the servlet container has resources it will need to cleanup when the JVM really exits.)

The correct way to handle this case is to clean up your threads in the destroy() method. This means starting them in a way that lets you gently stop them in a correct way. Here is an example (where MyThread is one of your threads, and extends ServletManagedThread):

public class MyServlet extends HttpServlet {
private List threads = new ArrayList();

// lots of irrelevant stuff left out for brevity

public void init() {
ServletManagedThread t = new MyThread();
threads.add(t);
t.start();
}

public void destroy() {
for(ServletManagedThread thread : threads) {
thread.stopExecuting();
}
}
}

public abstract class ServletManagedThread extends Thread {

private boolean keepGoing = true;

protected abstract void doSomeStuff();
protected abstract void probablySleepForABit();
protected abstract void cleanup();

public void stopExecuting() {
keepRunning = false;
}

public void run() {
while(keepGoing) {
doSomeStuff();
probablySleepForABit();
}
this.cleanup();
}
}




Anonymous said...

Indeed, destroy() method is there for a reason and that is cleanup. This is also very important to prevent memory leak in Java application e.g. closing any database connection or releasing file handlers etc. In any case, you should not call System.exit() if you are running in a java server e.g. tomcat, glassfish, weblogic, websphere or jboss.

Verhás Péter said...

If the servlet container runs servlets under the default security context on a mission critical server it deserves to be crashed. And sysadmin should be fired.

rockey said...

i have a web application running in production on linux server so how can i stop that application and deploy my new jars ?what is the correct way

Javin Paul said...

Hello @rockey, if you just have your web application deployed in the server then you can stop the server, deploy new WAR file and restart the server. If it contains other application which cannot be stopped, then you need a webapp similar to manager webapp of tomcat. The stop and start the server is what many company use.

Post a Comment