La JVM tiene un límite artificial de 1024 entradas que puede tener en el seguimiento de la pila de una excepción o un error, probablemente para ahorrar memoria cuando ocurre (ya que la máquina virtual tiene que asignar memoria para almacenar el seguimiento de la pila)
Afortunadamente, hay una bandera que permite aumentar este límite.Sólo tiene que ejecutar su programa con el siguiente argumento:
-XX:MaxJavaStackTraceDepth=1000000
Esto imprimirá hasta 1 millón de entradas de su seguimiento de la pila, lo que debería ser más que suficiente. También es posible establecer este valor en -1
para establecer el número de entradas como ilimitadas.
This list of non-standard JVM options da más detalles:
Max. no. de líneas en el seguimiento de la pila para excepciones de Java (0 significa todo). Con Java> 1.6, el valor 0 realmente significa 0. valor -1 o cualquier número negativo debe ser especificado para imprimir toda la pila (probado con 1.6.0_22, 1.7.0 en Windows). Con Java < = 1.5, el valor 0 significa todo, JVM ahoga el número negativo (probado con 1.5.0_22 en Windows).
Ejecución de la muestra de la pregunta con esta bandera da el siguiente resultado:
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)
De esta manera, se pueden encontrar las personas que llaman originales del código que arrojó el error, incluso si el seguimiento de pila real tiene más de 1024 líneas de largo.
Si no puede usar esa opción, existe otra manera, si está en una función recursiva como esta, y si puede modificarla. Si se agrega el siguiente 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.
}
}
Esencialmente, esto va a crear y lanzar una nueva StackOverflowError
, descartando la última entrada, ya que cada uno se enviarán en un nivel superior en comparación con la anterior (esto puede tomar una unos segundos, porque todos estos errores deben ser creados). Cuando la traza de la pila se reducirá a 1023 elementos, simplemente se volverá a tirar.
En última instancia, esto imprimirá las 1023 líneas en la parte inferior de la traza de la pila, que no es la traza completa de la pila, pero es probablemente la parte más útil de la pila.
Dado que puede aumentar el tamaño de la pila y desaparece, ¿puede intentar disminuir el tamaño de la pila y ver si eso le permite ver más trazas de la pila? No recuerdo cómo se controla el tamaño de la pila en la JVM y si se le permite hacerlo lo suficientemente pequeño, pero podría ayudar a diagnosticar el problema. –
@Tom, el tamaño de la pila está controlado por el nuevo 'Tema (grupo ThreadGroup, destino Runnable, nombre de cadena, stackSize largo)'. – bestsss
Oh bien. Buena idea :-( –