You have to run the logic. If an exception is guaranteed to be thrown then everything after it is not going to run. The compiler sees that.
The compiler sees that this exception is going to always be thrown. In the case of the question above, the finally bloc is supposed to always run (if there is not a System.exit(1) in the other blocs). To the compiler it sees that an exception is always thrown just like in my example I just gave.
It depends what you mean by "certainly". The compiler can't identify all possible infinite loops (in fact there's a mathematical theorem called the "Halting Problem" which proves that it's impossible to write a program to identify whether a program will terminate or not). But it does identify some of the more obvious infinite loops.
But I don't understand your goal. Do you want to be able to look at a program and figure out whether a loop will terminate? Or do you want to figure out whether the compiler will figure that out?