Когда JVM нормально отключается, это означает, что основной поток завершен. Если JVM закрывается для какого-либо другого режима (например, пользователь нажал Strg + C), основной поток все еще работает. Таким образом, вы можете сохранить ссылку на главный поток в своем хуке shutdown и проверить, жив ли этот поток. Конечно, это предполагает, что основной поток обычно будет последним запущенным потоком в вашем приложении. Я не знаю, какова ситуация, если один из потоков называется System.exit (), но вы можете легко это выяснить.