Дана следующая информация об исключении:
java.lang.RuntimeException: level 2 exception
at com.msh.demo.exceptionStack.Test.fun2(Test.java:17)
at com.msh.demo.exceptionStack.Test.main(Test.java:24)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
Caused by: java.io.IOException: level 1 exception
at com.msh.demo.exceptionStack.Test.fun1(Test.java:10)
at com.msh.demo.exceptionStack.Test.fun2(Test.java:15)
... 6 more
После стольких лет изучения Java вы действительно будете читать информацию об исключениях Java? Можете ли вы уточнить последовательность событий в процессе создания исключения?
Контент, который необходимо усвоить
Написать демонстрационный тест
Приведенная выше информация об исключении генерируется демонстрацией:
package com.msh.demo.exceptionStack;
import java.io.IOException;
/**
* Created by monkeysayhi on 2017/10/1.
*/
public class Test {
private void fun1() throws IOException {
throw new IOException("level 1 exception");
}
private void fun2() {
try {
fun1();
} catch (IOException e) {
throw new RuntimeException("level 2 exception", e);
}
}
public static void main(String[] args) {
try {
new Test().fun2();
} catch (Exception e) {
e.printStackTrace();
}
}
}
На этот раз я скопировал все содержимое файла, чтобы номера строк кода в статье соответствовали фактическим номерам строк один за другим.
Согласно приведенной выше информации об исключении, последовательность событий в процессе создания исключения следующая:
- В строке 10 Test.java выдается IOExceotion («исключение 1-го уровня») e1.
- Исключение e1 выбрасывается слой за слоем, пока не будет поймано в строке 15 Test.java.
- В строке 17 файла Test.java в соответствии с перехваченным исключением e1 выдается RuntimeException("исключение уровня 2", e1) e2
- Исключение e2 выбрасывается слой за слоем, пока не будет поймано в строке 24 Test.java.
- Других аномальных сведений в последующем нет.После необходимого фреймворка метод e2.printStackTrace() автоматически вызывается программой или активно пользователем
Как прочитать информацию об исключении
Итак, как прочитать информацию об исключении? Есть несколько вещей, о которых вам нужно знать:
-
Стек исключений печатается в порядке FILO.Исключение в нижней части содержимого печати генерируется первым, что постепенно приводит к возникновению исключения выше.. Исключение в верхней части печати — это последнее, которое было выброшено и не перехвачено. Считая сверху вниз,
i+1
Исключение составляет первыйi
причина, по которой было выбрано исключениеcause
, начиная с «Вызвано». - Каждое исключение в стеке исключений состоит из имени исключения + подробной информации + пути.. Имя исключения начинается в начале строки (или сразу следует за «Вызвано»), за которым следуют подробности (для лучшей читаемости необходимо указать соответствующие подробности), начиная со следующей строки, пропуская вкладку, это путь A позиция в , одна позиция в строке.
- Путь печатается в порядке FIFO, и позиция в верхней части содержимого печати является первой, которая передается исключением, и выбрасывается слой за слоем.. Самая ранняя переданная позиция — это позиция, в которой генерируется исключение, и отсюда может быть запущена обратная отладка; последующая позиция обычно является точкой входа для вызова метода, которую можно получить из стека методов, когда JVM перехватывает исключение . Для причины его печатный путь до тех пор, пока он не будет завернут в следующее исключение, а затем напечатано «... еще 6», что указывает на то, что причина является завернутым исключением, и после этого он также проходит через слой 6 позиций по слой, но эти местоположения дублируют путь, который является оберткой для исключения, поэтому они здесь опущены и напечатаны в пути, который является оберткой для исключения. Информация "...еще 6" не важна и может быть проигнорирована.
Теперь достаточно просто вернуться и прочитать информацию об исключении для примера?
Чтобы облегчить понимание, я описал структуру и элементы информации об исключении настолько просто, насколько это возможно, и могу внести некоторые недостатки. Чтение информации об исключениях — важный навык Java-программистов, и я надеюсь, что вы сможете усвоить его и забыть об этих длинных описаниях.
Если вы до сих пор не понимаете, предлагаю вам проследить процесс создания и печати исключения самостоятельно, просто используйте пример кода, это просто, но достаточно. Сложность в том, что исключения — это механизм, предоставляемый JVM, и нужно понимать реализацию JVM, а многие нативные методы вызываются внизу, и отслеживать нативный код не так удобно.
расширять
Почему иногда я вижу только имя исключения "java.lang.NullPointerException" в журнале, но не стек исключений
В информации об исключении из примера есть три элемента: имя исключения, подробная информация и путь.Детали и пути могут быть опущены из-за оптимизации JVM..
Это часто происходит в журнале серверных приложений.Поскольку одно и то же исключение было напечатано несколько раз, если одно и то же исключение продолжает печататься, JVM пропустит подробную информацию и очереди путей.Прокрутите вперед, чтобы найти полную информацию об исключении.
Brother Monkey уже сталкивался с этой проблемой при использовании сервера Yarn Timeline Server. Вы чувствуете это чувство? Блин, почему только имя исключения и нет стека исключений? Если нет стека исключений, как я могу узнать, где генерируется исключение? Не могу остановить онлайн-сервис, все зависит от лога!
Подобных случаев в сети много, напримерNullPointerException теряет информацию о стеке исключений, читатели могут обратиться к этой ссылке, чтобы поэкспериментировать.
Как добавить переменную-член в класс исключений
Чтобы правильно выразить исключение, нам иногда нужно настроить исключение и добавить некоторые переменные-члены, чтобы автоматически дополнять и печатать необходимую информацию при печати стека исключений.
Проследите код, выводящий стек исключений:
...
public void printStackTrace() {
printStackTrace(System.err);
}
...
public void printStackTrace(PrintStream s) {
printStackTrace(new WrappedPrintStream(s));
}
...
private void printStackTrace(PrintStreamOrWriter s) {
// Guard against malicious overrides of Throwable.equals by
// using a Set with identity equality semantics.
Set<Throwable> dejaVu =
Collections.newSetFromMap(new IdentityHashMap<Throwable, Boolean>());
dejaVu.add(this);
synchronized (s.lock()) {
// Print our stack trace
s.println(this);
StackTraceElement[] trace = getOurStackTrace();
for (StackTraceElement traceElement : trace)
s.println("\tat " + traceElement);
// Print suppressed exceptions, if any
for (Throwable se : getSuppressed())
se.printEnclosedStackTrace(s, trace, SUPPRESSED_CAPTION, "\t", dejaVu);
// Print cause, if any
Throwable ourCause = getCause();
if (ourCause != null)
ourCause.printEnclosedStackTrace(s, trace, CAUSE_CAPTION, "", dejaVu);
}
}
...
Проблема синхронизации меня пока не волнует, видно, что код для вывода имени исключения и подробной информации такой:
s.println(this);
JVM реализует полиморфные вызовы этой ссылки во время выполнения посредством динамического связывания. Если вы продолжите трассировку, в конце концов будет вызван метод toString() этого экземпляра. Самый низкий общий класс-предок всех исключений — это класс Throwable, который предоставляет реализацию toString() по умолчанию. Большинство распространенных классов исключений не переопределяют эту реализацию. Наши пользовательские исключения также могут напрямую наследовать эту реализацию:
...
public String toString() {
String s = getClass().getName();
String message = getLocalizedMessage();
return (message != null) ? (s + ": " + message) : s;
}
...
public String getLocalizedMessage() {
return getMessage();
}
...
public String getMessage() {
return detailMessage;
}
...
Очевидно, формат печати по умолчанию — это формат информации об исключении из примера: имя исключения (полное имя) + подробная информация. DetailMessage устанавливается пользователем при создании исключения, поэтому, если есть пользовательская переменная-член, мы обычно вставляем эту переменную в метод toString(). Ссылаться наcom.sun.javaws.exceptions
в упаковкеBadFieldException
и посмотрите, как он вставляет поле и значение пользовательских переменных-членов:
public String toString() {
return this.getValue().equals("https")?"BadFieldException[ " + this.getRealMessage() + "]":"BadFieldException[ " + this.getField() + "," + this.getValue() + "]";
}
Строго говоря,
BadFieldException
Переменная-член поля не вставляется непосредственно в toString. Однако это не влияет на наше понимание, и заинтересованные читатели могут самостоятельно прочитать исходный код.
Суммировать
Согласно информации об исключении, отладка является базовым навыком для программиста.Здесь мы сделали предварительное исследование процесса чтения и печати информации об исключении.Мы также разберемся с часто используемыми классами исключений в будущем.Несколько основных правил, которые должны помнить программисты, чтобы лучше понять, как использовать исключения для написания чистого кода.
Довольно совершенный механизм обработки исключений в Java — это палка о двух концах: при правильном использовании он может улучшить читабельность и надежность кода, при плохом — сделать код более неуправляемым. Например, вызов метода-члена для нулевого указателя вызовет исключение во время выполнения, что естественно, однако неконтролируемо ждать, пока он вызовет исключение в определенной точке и месте (на самом деле «определено»). , но является «неопределенным» для отладки), или можно контролировать проверку и активную выдачу исключений в начале метода ввода? Кроме того, какие исключения следует обрабатывать немедленно, а какие следует продолжать выбрасывать на внешний уровень? Когда вы бросаете на внешний слой, когда вам нужно обернуть исключение? Взгляните на String#toLowerCase(), см. ProcessBuilder#start() и почувствуйте это.
Ссылка на эту статью:Вы действительно читаете сообщения об исключениях Java?
автор:обезьяна 007
Источник:monkeysayhi.github.io
Эта статья основана наCreative Commons Attribution-ShareAlike 4.0Международное лицензионное соглашение выпущено, его можно перепечатать, вывести или использовать в коммерческих целях, но авторство и ссылка на эту статью должны быть сохранены.