JVM имеет искусственное ограничение в 1024 записи, которое вы можете иметь в трассировке стека «Исключение или ошибка», возможно, для сохранения памяти при ее возникновении (поскольку виртуальная машина должна выделять память для хранения трассировки стека).
К счастью, есть флаг, позволяющий увеличить этот лимит. Просто запустите вашу программу со следующим аргументом:
-XX:MaxJavaStackTraceDepth=1000000
Это напечатает до 1 миллиона записей вашей трассировки стека, чего должно быть более чем достаточно. Также возможно установить это значение на -1
, чтобы установить количество записей как неограниченное.
Этот список нестандартных опций JVM дает более подробную информацию:
Макс. нет. строк в трассировке стека для исключений Java (0 означает
все). При Java> 1.6 значение 0 действительно означает 0. значение -1 или любой
необходимо указать отрицательное число для печати всей стопки (проверено с помощью
1.6.0_22, 1.7.0 в Windows). При Java <= 1.5 значение 0 означает все, JVM задыхается от отрицательного числа (протестировано с 1.5.0_22 на
Windows). </p>
Запуск образца вопроса с этим флагом дает следующий результат:
Exception in thread "main" java.lang.StackOverflowError
at Overflow.<init>(Overflow.java:3)
at Overflow.<init>(Overflow.java:4)
at Overflow.<init>(Overflow.java:4)
at Overflow.<init>(Overflow.java:4)
(more than ten thousand lines later:)
at Overflow.<init>(Overflow.java:4)
at Overflow.<init>(Overflow.java:4)
at Overflow.a(Overflow.java:7)
at Overflow.main(Overflow.java:10)
Таким образом, вы можете найти исходных кодов кода, выдавшего ошибку, даже если фактическая трассировка стека превышает 1024 строки.
Если вы не можете использовать эту опцию, есть еще один способ, если вы находитесь в рекурсивной функции, подобной этой, и можете ли вы ее изменить. Если вы добавите следующий try-catch:
public Overflow() {
try {
new Overflow();
}
catch(StackOverflowError e) {
StackTraceElement[] stackTrace = e.getStackTrace();
// if the stack trace length is at the limit , throw a new StackOverflowError, which will have one entry less in it.
if (stackTrace.length == 1024) {
throw new StackOverflowError();
}
throw e; // if it is small enough, just rethrow it.
}
}
По сути, это создаст и выбросит новый StackOverflowError
, отбрасывая последнюю запись, потому что каждая будет отправлена на один уровень выше по сравнению с предыдущей (это может занять несколько секунд, потому что все эти ошибки должны быть созданы ). Когда трассировка стека будет уменьшена до 1023 элементов, она просто перебрасывается.
В конечном итоге это выведет 1023 строки в нижней части трассировки стека, которая не является полной трассировкой стека, но, вероятно, является наиболее полезной ее частью.