Why doesn't the JVM recognize that a System.exit(0) will not allow any other code to execute, but complains about unreachable statements if a return will not allow code to be executed?
It's not the JVM - it's the compiler. And the compiler doesn't know what library calls will do - it only knows the language rules. (In particular, JLS section 14.21, Unreachable Statements.)
So for example:
public int foo() {
alwaysThrow();
// This is required.
return 10;
}
private static void alwaysThrow() {
throw new RuntimeException();
}
vs
public int foo() {
throw new RuntimeException();
// Error: unreachable statement
return 10;
}
That simple inlining changes the meaning of the code as far as the compiler's concerned.
This could be "fixed" by having a return type of "never" - to indicate "this method never returns normally - it either hangs or throws an exception" but that's simply not part of the language (and would have its own complications). If you're interested, Eric Lippert has a couple of blog posts on this topic with regard to C# (which is in a similar position): part one, part two.