Краткий ответ: перехватить исключение и распечатать сообщение поле . Вы можете сделать это в блоке try
… catch
в функции верхнего уровня или (лучше) в UncaughtExceptionHandler .
Длинный скучный ответ:
Исключение будет передаваться из каждой функции вызывающей стороне до тех пор, пока оно не найдет ее с включающим блоком try
… catch
.
Таким образом, один из подходов состоит в том, чтобы поймать исключение самостоятельно, например:
fun main() {
try {
// All your top-level code here…
} catch (x: Exception) {
System.err.println(x.message)
}
}
Если вы используете каркас журналирования, вы можете использовать его вместо этого, конечно.
Если нет вложенного try
… catch
, он будет вызывать UncaughtExceptionHandler - или, если у потока его нет, его ThreadGroup или, если это не так, значение по умолчанию .
Если вы не укажете значение по умолчанию, системный вызовет метод printStackTrace () , который печатает сообщение об исключении и всю его обратную трассировку в стандартный поток ошибок - вот почему вы видите след показан в вопросе.
Таким образом, другой подход заключается в установке UncaughtExceptionHandler на одном из этих уровней, например ::
Thread.setDefaultUncaughtExceptionHandler { t, x ->
System.err.println(x.message)
}
Это намного безопаснее, потому что это работает для всех потоков.
Если вы пишете простое приложение, которое использует только один поток, то может быть просто поймать исключение в вашем методе верхнего уровня. Но если вы пишете что-то, что использует GUI-инструментарий или веб-фреймворк, или использует сопрограммы или другую фреймворк, или запускаете какие-либо потоки вручную, то, вероятно, будут запущены другие потоки. Это имеет два эффекта:
Во-первых, у вас не будет доступа к методам верхнего уровня этих потоков, и вы не сможете перехватывать там исключения. Так что UncaughtExceptionHandler является единственным способом. (По умолчанию он самый безопасный, поскольку у вас, вероятно, не будет доступа ни к темам, ни к группам нитей.)
Во-вторых, хотя поток с исключением прекратит работу, другие потоки не будут. Таким образом, JVM не будет закрыта, и другие потоки будут продолжать работать, не подозревая. Это оставляет ваше приложение в несовместимом состоянии, что может иметь катастрофические последствия: вы можете получить задания, стоящие в очереди, но никогда не запускающиеся, или другие потоки, останавливающие ожидание данных, или запросы, оставшиеся без ответа, или вообще что-нибудь, в зависимости от состояния вашего приложения. структурированный и какой поток умер. А поскольку JVM продолжается, мониторы системного уровня или менеджеры служб не будут знать, что в этом нет ничего плохого.
Так что после регистрации исключения, в некоторых случаях для вашего обработчика может быть очень хорошей идеей завершить работу всего приложения.
(Кстати, третий подход заключается в использовании пользовательского Exception
и переопределении его printStackTrace()
метода для печати только сообщения. Но это не очень хорошая идея; он отрицает намерение этого метода, которое может вызвать все виды проблем для всего, что его использует.)