How is Java's exception hierarchy organised, and what sits at the top of it?
Everything throwable in Java descends from java.lang.Throwable, which has two direct subclasses and therefore two separate branches.
Exception is the branch for conditions a program can reasonably be expected to handle. It splits again. Its unchecked branch is RuntimeException, which holds NullPointerException, IllegalArgumentException, IllegalStateException, IndexOutOfBoundsException, ArithmeticException, ClassCastException and the rest — the errors that indicate a bug in the program rather than an expected external failure. Its checked branch holds everything else that extends Exception but not RuntimeException: IOException, SQLException, ParseException, ClassNotFoundException. These represent conditions outside your control, such as a file being absent or a network being down, and the compiler forces you to acknowledge them.
Error is the branch for problems the JVM itself cannot recover from: OutOfMemoryError, StackOverflowError, InternalError, NoClassDefFoundError. These are not about your logic. The JVM throws them when it cannot continue, and the only reasonable responses are to let the process die so a supervisor restarts it, or to free resources and try to carry on.
The design intent is that a catch clause for Exception means "I handle failures that are part of normal operation", while the absence of RuntimeException under Exception means that the unchecked branch deliberately does not force the caller to write boilerplate for what are almost always programming mistakes.