Бывает, видишь в логе исключение, а стек трейса у него нет (он пустой):
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException
Одна строка и всё.
Это происходит, когда программа кидает очень много таких исключений. Сначала они генерируются как надо, с заполненным стек трейсом, и полностью попадают в лог. Потом виртуальная машина решает, что раз такие ошибки происходят очень часто, имеет смысл оптимизировать генерацию этих исключений (см. JIT). Тогда-то у них и пропадает стек трейс.
Поэтому когда вы у себя такое видите и не можете понять, откуда эти исключения вылетают, имеет смысл промотать лог назад (очень далеко назад, как правило) и поискать в том месте, где они впервые появились. И/или можно выключить эту оптимизацию с помощью следующего аргумента JVM
-XX:-OmitStackTraceInFastThrow
Если интересно, можно сымитировать подобную ситуацию простой программой:
public class Main2 {
public static void main(String... args) {
for (int i = 0; i < 1000000; i++) {
try {
int x = 0 / 0;
} catch (Exception e) {
if (e.getStackTrace().length == 0) {
System.out.println("i=" + i);
throw e;
}
}
}
}
}
У меня, например, цикл заканчивается на 12288-й итерации.
Мне не совсем понятна философия этой оптимизации. Да, исключения действительно “тяжёлые”. Но на то они и исключения, что должны происходить редко. И если в вашей программе они выкидываются очень часто, вы явно что-то делаете не так, и плохая производительность — это не главная ваша проблема. Ваша проблема в том, что вы не читали Item 57: Use exceptions only for exceptional conditions из Effective Java Блоха.
Может быть, кто-нибудь из читателей может объяснить?