Is there a use case where Error is manually thrown?

Viewed 46

I know it's a very noob question.

I have been going through blogs and articles trying to understand why and where Errors are used in Java, but no luck. In practice, I have never seen Errors being used and given that an Error occurs in an Abnormal condition.

Are these just for the internal libraries to use? Can it be manually thrown in a program? May be, we're not supposed to do it, but can we?

2 Answers

You can throw them if you want. This is legal java code and runs fine:

class Example {
  public static void main(String[] args) {
    throw new Error();
  }
}

Just like runtime exceptions you don't need to declare that you do so (imagine you had written throw new IOException();, then it would not compile unless you turn that into …main(String[] args) throws IOException. RuntimeExceptions and Errors do not require being explicitly listed, however.

There is a ton of code out there that catches all exceptions. These are usually 'entrypoint controllers' - things that start applications. Java itself starts your main (and will catch anything main throws, and turn that into a nice print on the command line), but web servers and app servers and plugin runners all do similar things: A web server will receive an HTTP request, figure out which handler code is supposed to be invoked to deal with it, (someone wrote the web framework - but you wrote that handler), and will then catch any and all exceptions that fall out of that handler, to then serve up a 500 error and log a bunch of info about this event. Your public void doGet() or whatnot that you have to in your web handler is an entry point, and the point where the webframework invokes it, is called an entrypoint controller.

Most entrypoint controllers have a legitimate:

try {
    invokeEntryPoint();
} catch (Exception e) {
    // deal with it...
    // web frameworks would log the request, for example.
}

Many controllers do not catch error, and that is the pragmatic primary difference between a runtimeexception and an error: RuntimeExceptions and Errors do not need to be stated in throws clauses, but RuntimeExceptions are routinely caught, especially by entrypoint controllers, whereas errors often are not, and thus they result in a more thorough unwinding of the stack: It 'shuts down' deeper into the process. With a web server it may take down the entire webserver. This can be a good idea, for example, if a JVM invariant is broken because of disk corruption of the VM, or the system is out of memory, that can be a better option than just catching the error, logging (that logging itself could then be impossible due to memory issues), and continuing. Let the OS watchdog reboot the server automatically.

That's the pragmatic difference.

So, when should you throw an Error? Very rarely, but it is warranted if you have detected a violation of fundamental assumptions about your app, i.e. a bug or a misconfiguration (vs. an event that can reasonably occur during normal operation, such as an image file that was uploaded by a user that isn't valid). A common occurence of this is if you use YourClass.class.getResource("states.txt") to retrieve some data file that is as much a part of your application as your class files are: If that is missing, well, then your installation is corrupt, and the drastic nature of Error is quite warranted:

try (InputStream in = AbichandanisApp.class.getResource("splash_screen.png")) {
    if (in == null) throw new Error("Resource missing: splash_screen.png");
    renderSplashScreen(new Image(in));
}

That's an example of appropriate use of throwing Error.

Related