10

I understand exceptions, throwing them, handling them, and propagating them to a method lower in the call stack (i.e. throws).

What I don't understand is this:

public static void main(String[] args) throws Exception {
    ...
}

Now, I assume that in the case that main throws an Exception, the JVM handles it (correct?). If that's the case, then my question is:

How does the JVM handle exceptions thrown by main? What does it do?

19

You might think that the public static void main method in Java or the main function in C is the real entry point of your program – but it isn't. All high-level languages (including C) have a language runtime that initializes the program, and then transfers control flow to the entry point. In the case of Java, initialization will include:

  • setting up the JVM
  • loading required classes
  • running static initializer blocks. This can execute user-defined code before main is invoked. These blocks aren't supposed to throw exceptions.

There are a variety of ways to implement exception handling, but for the purpose of this question, they all can be viewed as a black box. The important thing however is that the language runtime must always provide an outermost exception handler that catches all exceptions that aren't caught by user code. This exception handler will usually print out a stack trace, shut down the program in an orderly fashion, and exit with an error code. Properly shutting down the program includes destroying the object graph, invoking finalizers, and freeing resources such as memory, file handles, or network connections.

For purposes of illustration, you can imaging the runtime wrapping all code in a giant try-catch that looks like

try {
    loadClasses();
    runInitializers();
    main(argv);
    System.exit(0);
} catch (Throwable e) {
    e.printStackTrace();
    System.exit(-1);
}

except that it's not necessary for a language to actually execute code like this. The same semantics can be implemented in the code for throw (or equivalent) that searches for the first applicable exception handler.

9

All Java code runs in the context of a thread. The linked JavaDoc explains the error handling and exit criteria, but here is the gist of it:

  • The JVM spins itself up and prepares the execution environment.
  • The JVM creates a thread which will run the main() method using whatever command-line parameters are applicable.
  • The JVM sets a default uncaught exception handler that prints the exception to standard error and terminates.
  • The JVM executes the thread.

In the case of an uncaught exception, the program effectively dies per the third item above. This behavior is further specified in the Java Language Specification, Section 11.3


Additional info

Others have mentioned static blocks and how they execute before main(). However, this requires a bit more explanation to understand correctly.

When loading a class, the class loader must initialize all static final state and run all static blocks before the class can be used, to include instantiating instances of the class (aside: create a Java class where a class constant is initialized in a static block after creating an instance of the class, and the constructor references the constant. Boom!). However, this all happens in the class loader logic before any code can reference the class. Furthermore, the class is loaded in whatever thread referenced the class.

What this means is if the class containing main() references another class (e.g. class constant) then that class must be loaded before main() executes to include its static blocks. Otherwise, the static blocks are executed as above. If the class fails to load, then the class containing main() will also fail to load and the program will terminate.

Another FYI: static blocks can throw. Errors are thrown as-is. Exceptions are forbidden (compile-time error). RuntimeExceptions are wrapped in ExceptionInInitializerError. These are handled per the uncaught exception handler, which will typically either kill the thread or the application (main thread) unless you carefully wrap the class reference (and loading) in a try-catch.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.