Creo que lanzar una excepción es lo que debes hacer cuando algo sale mal. De esta forma, si su aplicación no se ejecuta como una aplicación independiente, la persona que llama puede reaccionar ante ella y tiene alguna información sobre lo que salió mal. También es más fácil para la depuración porque también tiene una mejor idea de lo que salió mal cuando ve un seguimiento de la pila.
Una cosa importante a tener en cuenta es que cuando la excepción alcanza el nivel superior y hace que la VM salga, la VM devuelve un código de retorno de 1, por lo tanto, las aplicaciones externas que usan el código de retorno ven que algo salió mal.
El único caso donde creo que System.exit() tiene sentido es cuando su aplicación debe ser llamada por aplicaciones que no son Java y por lo tanto tiene que usar códigos de retorno para ver si su aplicación funcionó o no y desea esas aplicaciones tienen la posibilidad de reaccionar de manera diferente sobre diferentes cosas que van mal, es decir, necesita diferentes códigos de retorno.