System.exit(), is there any alternative?

Hello fellow Java programmers!

Im working on an application that is intended to be used by collage students, it’s an educational program. Im working on some smooth way of shutting the program down when something goes wrong. I’ve read around a bit and System.exit(1) seems to be what I need, but I also read everywhere that it’s a very drastic way of shutting down a program, is there any way of smoothly shutting down a program after a nullpointer has occurred?

The nullpointer is caught within an object which does not have any references to any other classes. I decided to catch the exception so that I could present the user with a non-cryptic error message, but since the object does not have any references to any other classes, I can’t call the method I built for smoothly shutting the program down.

So, my question to you guys is: can System.exit(1) be used to shut down a program if a nullpointerexception occurs, without breaking something or messing stuff up that is?
If yes, then I’ll use.
If yes but it’s not recommended, what would you recommend?
If no, what should I do?

//Kurten

A bit more information about the problem would probably help us help you :slight_smile:
What does the program do, what is the architecture?

Normally (in a single threaded program) you would let the exception propagate to a place where it is reasonable to handle the exception and initiate a display of the non-cryptic error message you describe. If you really feel this is in your class without reference, you can try to make the error-handling method static or hand a reference to the error-handler object.
In general, I would suggest letting the exception propagate and be handled further out (by declaring that the methods in questions throws the given type of exception or a super-type).

If you’re in a threaded environment things often become a bit more complicated, so again more information would be nice.

Edit: Remember that your program will normally shut down when control returns from the main method (there are some exceptions, especially using Swing)

Hope it helps for now :slight_smile:

  • Scarzzurs

Thanks for the suggestions! :slight_smile:

Ok, let’s see if I can explain the architecture

Tha classes involved is: MainClass, GraphicsEngine, InputListener, Button.

MainClass implements Runnable and has references to GraphicsEngine, and InputListener. Hosts the shutdown method that looks like this:

public void stopAll(){
		inLis.listening = false; //Stops input listening
		ge.looping = false; //Stops graphics drawing
		running = false; //Stops everything within this class
	}

GraphicsEngine implements Runnable and has references to MainClass and Button, it also hosts a method that forwards a shutdown command to MainClass.
InputListener implements Runnable and has references to GraphicsEngine and MainClass

All these classes has a while loop that is controlled by the booleans in the stopAll() method. Therefore the program stops quite fluently when setting them to false.

Now onto Button
Button has no references, GraphicsEngine has an Array of Buttons that is drawn onto the screen, I initialized the Button array by using an Array initializer, and due to Button’s constructor, it is difficult to handle any exception thrown inside the Button class, outside it’s constructor.
The constructor looks like this:

public Button(String buttonsection, String filenamenotpressed, String filenamehovered, int posx, int posy){
		try{
			img = loadImage(filenamenotpressed);
		}catch(NullPointerException nullpointer){
			System.err.println("Shit just hit the fan and image " + filenamenotpressed + " can't be loaded");
			System.err.println("If you are not familiar with Java or C# programming techniques, don't panic");
			System.err.println("Simply stand up, wave your arms like a raving idiot, and scream in anguish!");
			System.err.println("If you are a Java or C# programmer, take a look at this stack trace, then give it to the developer");
			nullpointer.printStackTrace();
		}
		
		try{
			imgPressed = loadImage(filenamehovered);
		}catch(NullPointerException nullpointer){
			System.err.println("Shit just hit the fan and image " + filenamenotpressed + " can't be loaded");
			System.err.println("If you are not familiar with Java or C# programming techniques, don't panic");
			System.err.println("Simply stand up, wave your arms like a raving idiot, and scream in anguish!");
			System.err.println("If you are a Java or C# programmer, take a look at this stack trace, then give it to the developer");
			nullpointer.printStackTrace();
		}
		
		setX(posx);
		setY(posy);
		section = buttonsection;
	}

The loadImage method like this:

@Override
	public Image loadImage(String path){
		System.out.println("Loading image: " + path);
		Image tempImg = new ImageIcon(getClass().getResource(path)).getImage();
		if(tempImg != null){
			System.out.println("Image " + path + " loaded without errors");
			return tempImg;
		}else{
			throw new NullPointerException();
		}
	}

I hope this information is useful

A NullPointerException is a RuntimeException (not a checked one) and RuntimeException normally should not be catched. If it has to be catched, System.exit(1) is a valid option in a desktop application, but not on a server.

The usual best approach is to let the Exception bubble up to either the main thread or the application container. So in a desktop application, the main thread is the right place to catch it and present a human readable message to the user.

If you have additional information to the exception, catch it and throw an appropriate RuntimeException Subtype (like e.g. IllegalArgumentException) with a helpful message and append the original Exception as cause.

If you catch a RuntimeException in a codeblock that is recoverable, the Exception should be logged or presented to the user and the program should continue. Never, ever catch-log-rethrow.

If you catch a RuntimeException in a codeblock that is not recoverable, but could be in a calling codeblock, throw an appropriate checked Exception with a helpful message and append the original Exception as cause.

If you need to do something on shutdown, use a shutdown hook: http://download.oracle.com/javase/1.5.0/docs/api/java/lang/Runtime.html

Regarding exception handling in general, this is a must-read: http://today.java.net/article/2006/04/04/exception-handling-antipatterns

Thanks for the info Cylab, I’ll dig into the text about Exception handling! However, I find it difficult catching the exception after it leaves Button, Button is initialized in the class body of GraphicsEngine, which stops me from catching anything there, GraphicsEngine is initialized in the class body of MainClass, which makes it difficult to catch there as well =/

But, if System.exit is a valid option as you say, i’ll guess i will use it for now.

EDIT: I just noticed that I could move the GraphicsEngine initialization to a method which initializes some other stuff, so I can catch the exception there :slight_smile: Let’s see if it works, thanks for all your help guys, I love this community! :smiley:

2nd EDIT: I just tested it and it worked perfectly, I didn’t even have to call System.exit(1), the program shut itself down automatically along with the error message :smiley: Once again, thanks guys!

Actually your example shows more like how you don’t do it. :stuck_out_tongue:

  1. You don’t throw Exceptions without messages
  2. You usually don’t throw NullPointerExceptions yourself. In fact, only throw RuntimeExceptions at all, if you are really sure, they are not recoverable
  3. In your case loadImage should declare and throw new IOException(“Could not load Image from file '”+filename+"’")
  4. Missing button images should be considered recoverable - just catch the IOException, log a warning and use text-buttons instead.
  5. If you consider images on your buttons as mandatory in your application, the Button constructor should declare IOException and don’t catch it at all, so the application code setting up the buttons knows what Exception can occur and has to handle it.

Hmm, I thought the code work well, but I also understand there is a reason why certain conventions should be followed, which means I will rewrite the exception handling :stuck_out_tongue:

I would consider loading of the images critical since I have methods within them that InputListener and GraphicsEngine is dependent on. So if a button image can’t be loaded I want the program to close down and not try to recover.

I will switch the Nullpointer to an IOException instead since that seems more appropriate, the reason I went with Nullpointer was that the image file that would be returned by the loadImage() would have been null.

Thanks once again for the suggestions ^^ I will try to implement them as good as I can ^^

Hahaha…!

[quote]Crysis 2 could not load the player model. Loading text based Crysis 2 instead.
[/quote]
Awesome!

Awesome!
[/quote]


              ,.,
            .'   ',
            i  - -|
           ( | o o)
            |/ _")/
             \|__/
          ___|_  |__
        (^^^  .\ ^^^]
        | \   .|   | \
        |~ \  .|   |  \
        |  |  .|   |\  \
        \  |==={}==| \__]
         \_]_______\   Y\
          Y\    _  \
          l    / \__)
          |__ |   |*\
           |**|  /**/
           |**/ (**\
         __\**|  \**\
        /*****\   \*_|
        ^^^^^^^     ^^  

;D


              ,.,      [b]MAXIMUM STRENGTH![/b]
            .'   ',   /
            i  - -|  / 
           ( | o o)
            |/ _")/
             \|__/
          ___|_  |__
        (^^^  .\ ^^^]
        | \   .|   | \
        |~ \  .|   |  \
        |  |  .|   |\  \
        \  |==={}==| \__]
         \_]_______\   Y\
          Y\    _  \
          l    / \__)
          |__ |   |*\
           |**|  /**/
           |**/ (**\
         __\**|  \**\
        /*****\   \*_|
        ^^^^^^^     ^^  

;D
[/quote]
FTFY xD

Yeah I would never ever call System.exit() in a GUI-based program. At the very worst, show a popup that says “You must restart the app” with an OK button that then calls System.exit() only after relaunching the app automatically. You should always let the user decide what to do, and you should always try to recover from errors if possible. A user will never care unless their experience gets so bad they can’t do what they want to do. You forcibly make it that bad if you quit the app.

I do not expect this exception to be generated very often, there is only 2 possible errors that can trigger it, that I can think of anyway. One of those is sloppyness by me, in case I have misspelled something in the image path. In this case, the user can’t do anything with the application and I will have to fix it, which requires me to be notified.
The other one is if one of the user messes around inside the jar file for some reason and move or delete an image file. In this case the error can be fixed by the user, but I doubt that regular students will understand what went wrong, I also plan to supervise the early tests so in case of a crash, I want the user to grab hold of me instead of believing that everything is well.

But for later versions of the program Im building I will try to work around the problem of contacting me every time the program crashes, so I will probably try to build some kind of recovery code later on.

System.exit(1); doesn’t sound that bad in a small educational program IMO. Sure, it is kind of a shock to the JVM, but as long as you don’t use shutdown hooks or similar stuff it shouldn’t be a problem.

Another solution is to just use DOUBLE COMPILE!!!

[quote=“theagentd,post:13,topic:37206”]
Why should a shutdown hook be a problem on System.exit()?

[quote=“cylab,post:14,topic:37206”]

Oh. They are apparently executed before exiting. My bad. Ignore that.

http://data.fuskbugg.se/skalman02/02823390_double%20compile.PNG

The exit status of this program is OVER 9000!!! 8)

… but there is no reason to do something like that. poke
Hehe.