Alternatives to System.exit(1) - java

For various reasons calling System.exit is frowned upon when writing Java Applications, so how can I notify the calling process that not everything is going according to plan?
Edit: The 1 is a standin for any non-zero exit code.

The use of System.exit is frowned upon when the 'application' is really a sub-application (e.g. servlet, applet) of a larger Java application (server): in this case the System.exit could stop the JVM and hence also all other sub-applications. In this situation, throwing an appropriate exception, which could be caught and handled by the application framework/server is the best option.
If the java application is really meant to be run as a standalone application, there is nothing wrong with using System.exit. in this case, setting an exit value is probably the easiest (and also most used) way of communicating failure or success to the parent process.

I agree with the "throw an Exception" crowd. One reason is that calling System.exit makes your code difficult to use if you want other code to be able to use it. For example, if you find out that your class would be useful from a web app, or some kind of message consuming app, it would be nice to allow those containers the opportunity to deal with the failure somehow. A container may want to retry the operation, decide to log and ignore the problem, send an email to an administrator, etc.
An exception to this would be your main() method; this could trap the Exception, and call System.exit() with some value that can be recognized by the calling process or shell script.

System.exit() will block, and create a deadlock if the thread that initiated it is used in a shutdown hook.

Our company's policy is that it's OK (even preferred) to call System.exit(-1), but only in init() methods. I would definitely think twice before calling it during a program's normal flow.

I think throwing an exception is what you should do when something goes wrong. This way, if your application is not running as a stand-alone app the caller can react to it and has some information about what went wrong. It is also easier for debugging purposes because you as well get a better idea about what went wrong when you see a stack trace.
One important thing to note is that when the exception reaches the top level and therefore causes the VM to quit the VM returns a return code of 1, therefore outside applications that use the return code see that something went wrong.
The only case where I think System.exit() makes sense is when your app is meant to be called by applications which are not Java and therefore have to use return codes to see if your app worked or not and you want those applications to have a chance to react differently on different things going wrong, i.e. you need different return codes.

It can be dangerous / problematic in web servlet environments also.
Throwing an Exception is generally considered the other alternative.

Throwing exceptions is the best way to send information about a certain error up and out of the app.
A number doesn't tell you as much as:
Exception at thread 'main': FileNotFoundException "The file 'foo' doesn't exist"
(or something close to that)

It's frowned upon for normal exits. If "not everything is going according to plan", then System.exit is fine.
Update: I should add that I assume your '1' has meaning that is documented somewhere.

I feel impelled to add some salt of mine too. This is a great question that always pops up when I write an application.
As everyone here seems to agree, you should be careful using System.exit(), and if possible, use exceptions. However, System.exit() still seems the only way to return basic informations to the system, and thus required if you want to make your application scriptable. If you don't need that, just throw an exception and be done with it.
But if (and only if) your application is single-threaded, then it's fine to use it -- it's guaranteed that no other stuff is going in, and no resources are open (at least if you consistently use the try-with-resource idiom, which I'd highly recommend as it also makes the code cleaner and more compact).
On the other hand, as soon as your application creates any kind of thread that may write resources, System.exit() is a total "no, no", because it can (and, with time, will) corrupt data.
To be able to use a multi-threaded and scripted application and still guarantee the data integrity, my best solution so far is to save any resource-modifying thread you create (for example by consistently using a factory method which adds the thread to the list), and also installing a shutdown hook that cleanly ends each thread by interrupting and joining it. As the shutdown hook is also called by System.exit(), this will guarantee (minus programming errors) that no thread is killed in mid-resource writing.
Oh yes, maybe I shouldn't even mention it, but: never, EVER, use that horrible System.halt() method. It just shoots the VM in the head and doesn't call any shutdown hook.

Related

Trigger AutoClosable on JVM Shutdown

TL;DR:
Is there a way to find out, that JVM-shutdown is only prevented from the threads started by my code? Is it for example possible to automatically trigger AutoCloseable.close() on Shutdown?
Context
I am building a library, that should be used by several customers. This means, besides providing a documentation, I can't enforce certain things.
Architecture
(I try to describe it as abstract as possible and avoid unnecessary details)
I have a "Manager" object (which is kind of a Factory), that is used to create a "Service" object, that in turn needs some data to work accordingly. Since that data is loaded from some "slow" backend service (which also might change from time to time), I use a separate (Daemon)-Thread that checks for updates and injects new data into that service as soon as available. (This also means that unless the first update, that service is simply in "noop mode". But that's ok.)
Now the "Updater" (which runs in my daemon thread) uses a library that again starts a thread when opening a connection and it's necessary to call "close" to ensure that this secondary thread is stopped - otherwise it is not possible, to shutdown the JVM properly.
As a safety-net I call the close() method inside the finalize() method of my "Manager" (which keeps a reference to all Updater instances). This is not 100% safe, since it's not predictable when GC runs (even more during shutdown!), but it's my only option.
Update: Here is some abstract example code that illustrates the architecture and the according problem
Problem
This architecture causes two possible pitfalls:
If the implementation does not keep a reference to the instance of the manager, it will be garbage collected at some point and trough the finalize method the necessary background updates will be stopped.
If the implementation keeps an instances of the manager, it must call the close method during the shutdown of the according system, otherwise the JVM can't terminate properly.
So my actual problem is the "potential unreliability" of the developers, which are using that library.
Does anyone have an idea how to build a solution, that could handle both pitfalls?
It would be nice to have some Auto-AutoCloseable ;) that is called during Shutdown (e.g by the DestroyJavaVM Thread or similar).
Solutions I tried unsuccessfully
Inside the Updater I am closing the "problematic" connection inside a "try-finally" block, but that daemon thread is not interrupted / stopped automatically as well.
I registered a Runtime.getRuntime().addShutdownHook(...) that would close all connections, but this shutdown hook is never called since a Shutdown is only initiated when all user-threads are stopped.
Update: Solved at my implementation, but not the problem
I solved my problem as I found that the third party library (RabbitMQ Client) offers a setThreadFactory method that I can use to ensure the spawned Threads are Daemon-Threads.
Good luck for me with my 3rd party library, but the described problem is still possible.
You want the AutoCloseable resources to be closed so the shutdown is orderly, I guess.
AutoCloseable objects should be used (by your library clients) in a manner that ensures they are closed when they are no longer needed. In almost all cases, they should be using a try-with-resources block, so they are closed even if an exception is thrown.
You should take advantage of that by requiring your library clients perform a controlled shutdown of each thread when they receive a request to shutdown the program. A thread performs a controlled shutdown by returning from each Runnable.run method, or throwing an exception from each Runnable.run method. I believe this is the only reliable means of closing resources, because it ensures nested resource allocations are reallocated in the correct order. More generally, as a library writer you can not know what other operations your library clients might want to do on shutdown, so you should give them complete control over the shutdown.
You can help them do that by having your library code properly handle InterruptedException and the Thread.interrupted flag.
Ok, I guess there is no good solution for that problem, but since I found that my 3rd party library gives the possibility to create Daemon-Threads, this is exactly what was necessary to fix it.
Maybe this is also a problem that should be solved on the "human level" by providing a good documentation and ensure a proper usage of AutoCloseable. A good developer should know how to deal with that.
From a technical point of view I found these possible solutions, which are just "safety nets" no one should rely on.
call "close()" inside the finalize method
I implemented a service, that can be used to register AutoClosable resources. It runs inside a Daemon-Thread and checks every few seconds, if it finds the JavaDestroyVM Thread and in such a case, closes all registered AutoClosables and stops itself.
Disclosure: If a system runs "outside of the main method" (the JavaDestroyVM Thread will run all the time), this is solution won't work.
Update: The RegisterAutoClosable-Service was a very ugly/hacky solution - I deleted it and plan to change the design, to avoid such situations, but finally it's the responsibility of the implementing developer to close opened resources properly.

Are there any circumstances under which ScheduledThreadPoolExecutor would completely stop working?

We are running a Java server app that is using ScheduledThreadPoolExecutor to manage some work. There are multiple instances running, for different types of work, but each instance only uses one thread. It's not important why this is as there's really no way around it. What we noticed on the production server is that one of these instances stopped working at some point, completely and silently. Restarting the server brought it back again, but the problem isn't solved.
I know that using scheduleAtFixedRate will stop if the task throws an exception at some point, but this isn't the case here. We had a recurrent task that simply stopped executing, and new tasks that used the schedule() method and still didn't execute. I presume that the thread it was using died and didn't start again.
My question is, are there any circumstances under which this could happen? Is there anything I should look out for?
It looks like the simplest explanation is the answer: all threads hang.
In my case the cause of this seems to be HTTP requests that never timeout. This can happen in certain situations and I am yet to find a good solution for the problem. I think the best option is to implement a timeout on the scheduled task itself to make sure we avoid any issues.

How is it possible to stop part of the system and leave the user interface still running?

I am building a system where there is a simple GUI which will trigger the system to execute. I implemented the system in a way that when an exception is thrown, System.exit(0) is called and so the application stops.
I would like the implementation to stop, as it is doing now, however I wish that the GUI would not be closed as well. I tried implementing the system in a separate thread, however when some exception was thrown, the application still closed down.
Is there a way to leave the UI open, but still stop the implementation?
You cannot use Java system.exit for that purpose because that function kills the instance of Java Virtual Machine that is running your code, consequently stopping all the threads of your application.
In order for System.exit to work the way you want it to right now, you would need to have two different processes, so that each of them would run in its own Java Virtual Machine. However, this will make it harder to link things together.
Ideally, you should add some sort of control in the implementation, so that your GUI thread could activate or deactivate a switch which would naturally stop the logic of the implementation. This really is the best way to go in my opinion.
Essentially, they will need to be separate applications. That is, make them separate processes, not separate threads.
This kind of loose-coupling between your UI and back-end will achieve the behaviour you want, and also yields a bunch of other benefits relating to separating the concerns of your UI and your backend.
No, there is no way to keep your UI open if your program is running on the same process. I suppose you could run your UI and your program as separate applications, but that seems tedious and error prone. If an exception is thrown, you should be notifying the user, not just exiting the JVM.

How do I make the JVM exit on ANY OutOfMemoryException even when bad people try to catch it

An OOME is of the class of errors which generally you shouldn't recover from. But if it is buried in a thread, or someone catches it, it is possible for an application to get in a state from which it isn't exiting, but isn't useful. Any suggestions in how to prevent this even in the face of using libraries which may foolishly try to catch Throwable or Error/OOME? (ie you don't have direct access to modify the source code)
Solution:
On newer JVMs:
-XX:+ExitOnOutOfMemoryError
to exit on OOME, or to crash:
-XX:+CrashOnOutOfMemoryError
On Older:
-XX:OnOutOfMemoryError="<cmd args>; <cmd args>"
Definition: Run user-defined commands when an OutOfMemoryError is first thrown. (Introduced in 1.4.2 update 12, 6)
See http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html
An example that kills the running process:
-XX:OnOutOfMemoryError="kill -9 %p"
If some piece of code in your application's JVM decides that it wants to try to catch OOMEs and attempt to recover, there is (unfortunately) nothing you that you can do to stop it ... apart from AOP heroics that are probably impractical, and definitely are bad for your application's performance and maintainability. Apart from that, the best you can do is to pull the plug on the JVM using an "OnOutOfMemoryError" hook. See the answer above: https://stackoverflow.com/a/3878199/139985/
Basically, you have to trust other developers not to do stupid things. Other stupid things that you probably shouldn't try to defend against include:
calling System.exit() deep in a library method,
calling Thread.stop() and friends,
leaking open streams, database connections and so on,
spawning lots of threads,
randomly squashing (i.e. catching and ignoring) exception,
etc.
In practice, the way to pick up problems like this in code written by other people is to use code quality checkers, and perform code reviews.
If the problem is in 3rd-party code, report it as a BUG (which it probably is) and if they disagree, start looking for alternatives.
For those who don't already know this, there are a number of reason why it is a bad idea to try to recover from an OOME:
The OOME might have been thrown while the current thread was in the middle of updating some important data structure. In the general case, the code that catches this OOME has no way of knowing this, and if it tries to "recover" there is a risk that the application will continue with a damages data structure.
If the application is multi-threaded there is a chance that OOMEs might have been thrown on other threads as well, making recovery even harder.
Even if the application can recover without leaving data structures in an inconsistent state, the recovery may just cause the application to limp along for a few seconds more and then OOME again.
Unless you set the JVM options appropriately, a JVM that has almost run out of memory tends to spend a lot of time garbage collecting in a vain attempt to keep doing. Attempting to recover from OOMEs is likely to prolong the agony.
Recovering from an OOME does nothing to address the root cause which is typically, a memory leak, a poorly designed (i.e. memory wasteful) data structure, and/or launching the application with a heap that is too small.
edit OutOfMemoryError.java, add
System.exit() in its constructors.
compile it. (interestingly javac
doesn't care it's in package java.lang)
add the class into JRE rt.jar
now jvm will use this new class. (evil laughs)
This is a possibility you might want to be aware of. Whether it's a good idea, or even legal, is another question.
User #dennie posted a comment which should really be its own answer. Newer JVM features make this easy, specifically
-XX:+ExitOnOutOfMemoryError
to exit on OOME, or to crash:
-XX:+CrashOnOutOfMemoryError
Since Java 8u92 https://www.oracle.com/java/technologies/javase/8u92-relnotes.html
One more thing I could think of (although I do not know how to implement it) would be to run your app in some kind of debugger. I noticed, that my debugger can stop the execution when an exception is thrown. :-)
So may be one could implement some kind of execution environment to achieve that.
How about catching OOME yourself in your code and System.exit()?
You can run your java program using Java Service Wrapper with an OutOfMemory Detection Filter. However, this assumes that the "bad people" are nice enough to log the error :)
One possibility, which I would love to be talked out of, is have a stupid thread thats job is to do something on the heap. Should it receive OOME - then it exits the whole JVM.
Please tell me this isn't sensible.
You could use the MemoryPoolMXBean to be notified when a program exceeds a set heap allocation threshold.
I haven't used it myself but it should be possible to shut down this way when the remaining memory gets low by setting an allocation threshold and calling System.exit() when you receive the notification.
Only thing I can think of is using AOP to wrap every single method (beware to rule out java.*) with a try-catch for OOME and if so, log something and call System.exit() in the catch block.
Not a solution I'd call elegant, though...

Is it likely appdomains will help in this scenario?

I have a dotnet process that through calls to an unmanaged dll is communicating with a Java process.
Under some circumstances, the Java process appears to be crashing and taking my dotnet process down with it. No exceptions are raised, the process just dies. Upon crashing, java is creating a log file with names like "hs_err_pid3228" etc.
Not having received any satisfaction from the vendor that is providing the unmanaged dll and the java process, I am reduced to trying to mitigate the problem which would necessitate ensuring the calls into the java process, if they crash, don't take down my process.
Having read various articles, appdomains seem a likely candidate to use - my theory being I can with a bit of work separate my functionality that calls the java process and run it in a separate appdomain, which will hopefully allow me to if not catch the appdomain going down, at least detect that it has happened and restart that functionality.
Has anyone had a similar sort of issue? Does this approach seem reasonable to those of you with more experience of appdomain?
To make it even more fun, the Java crash is not really reproducible - it seems very random and I'm still battling with how I'm going to TEST that separating into the appdomain
This is a reasonable use of AppDomains, and what you propose will work.
In a similar vein, I once used AppDomains to create a single application that watched for itself crashing for exception reporting purposes. The application started itself up, created a new AppDomain, then re-executed itself in the new AppDomain, which then detected it was running in an AppDomain and executed normally. When an exception happened in that AppDomain, the original process is notified, it tears down the child domain reports to the user that an error occured, asks whether they want to report it or not, then picked itself up and tried it all over again.
EDIT: To give you a headstart, if you want to look at the Program.cs for that project, I've uploaded a stripped down version here. (It's pretty long, so I didn't think I should post it here.)
Yep, leveraging AppDomains make a lot of sense here.
I've recently reworked my Windows service to load its various WCF services as plug-ins that operate within their own AppDomain. I've got a few cases in the bootstrapping process where I'm using MarshalByRefObject objects to get things up and running, but once the plug-ins are loaded, communication between the AppDomains is extremely easy using WCF.

Categories