¿Cómo detengo los stacktraces truncados en los registros?
-
22-07-2019 - |
Pregunta
Muchas veces en los registros de Java obtendré algo como:
Caused by: java.sql.BatchUpdateException: failed batch
at org.hsqldb.jdbc.jdbcStatement.executeBatch(jdbcStatement.java:1102)
at org.hsqldb.jdbc.jdbcPreparedStatement.executeBatch(jdbcPreparedStatement.java:514)
at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:48)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:242)
... 113 more
¿Alguien sabe cómo mostrar el seguimiento completo de la pila (es decir, mostrar las otras 113 líneas)?
El JavaDocs (para Java 7) para Throwable tiene una explicación bastante detallada de lo que está sucediendo.
Solución
Cuando vea '... 113 más', eso significa que las líneas restantes de la excepción 'causada por' son idénticas a las líneas restantes desde ese punto en adelante de la excepción principal.
Por ejemplo, tendrás
com.something.XyzException
at ...
at ...
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:242)
at ... <the other 113 lines are here>...
Caused by: <the above>.
Las dos trazas de la pila 'se encuentran' en AbstractBatcher.executeBatch, línea 242, y desde entonces la traza de llamada ascendente es la misma que la excepción de ajuste.
Otros consejos
Apache Commons Lang proporciona un buen método de utilidad ExceptionUtils.printRootCauseStackTrace () que imprime un seguimiento de pila anidado 'al revés'. El resultado es mucho más intuitivo.
Si ve el resultado al lado del original fuera del método printStackTrace (), quedará claro dónde fueron las '113 más' líneas.
Me gusta el ejemplo encontrado aquí :
HighLevelException: MidLevelException: LowLevelException
at Junk.a(Junk.java:13)
at Junk.main(Junk.java:4)
Caused by: MidLevelException: LowLevelException
at Junk.c(Junk.java:23)
at Junk.b(Junk.java:17)
at Junk.a(Junk.java:11)
... 1 more
Caused by: LowLevelException
at Junk.e(Junk.java:30)
at Junk.d(Junk.java:27)
at Junk.c(Junk.java:21)
... 3 more
Básicamente en el código fuente, main
llama a la función a
que llama a la función b
que llama ... a la llamada función e
.
Función e
arroja una LowLevelException
que hace que la función c capture la LowLevelException
y arroje una MidLevelException
(envolviendo el MidLevelException
. La clase Exception
tiene un constructor que puede aceptar una excepción diferente, envolviéndola). Esto hace que la función a capture la MidLevelException
y arroje una HighLevelException
que ahora envuelve las dos instancias anteriores de Exception
.
Como se señaló en las otras respuestas, el seguimiento de la pila no está realmente truncado, está viendo el seguimiento completo de la pila. El .. .3 more
en mi ejemplo está ahí porque de lo contrario sería redundante. Si quisiera ser redundante y desperdiciar líneas de salida, .. 3 más
podrían sustituirse por
at Junk.b(Junk.java:17)
at Junk.a(Junk.java:11)
at Junk.main(Junk.java:4)
Pero no hay necesidad de generar estas tres líneas, porque ya están implícitas.
Aumentar la opción JVM -XX: MaxJavaStackTraceDepth
.
Encontré esto útil para obtener la imagen completa. Obtenga un seguimiento completo de la pila de la Excepción y la causa (que a menudo muestra líneas repetidas de la Excepción principal, pero puede ser útil).
... catch( Exception e) ...
... catch( NoClassDefFoundError e)
{
for(StackTraceElement ste: e.getStackTrace())
{
System.out.println(ste);
}
if( e.getCause()!=null )
{
for(StackTraceElement ste: e.getCause().getStackTrace())
{
System.out.println(ste);
}
}
}
En una publicación de blog, acabo de describir cómo obtener algo más que " BatchUpdateException: lote fallido " : establezca hibernate.jdbc.factory_class = org.hibernate.jdbc.NonBatchingBatcherFactory
para deshabilitar el procesamiento por lotes en hibernación.
Normalmente, se puede usar BatchUpdateException.getNextException
para obtener la razón de la falla, pero en algunos casos esto puede devolver null
. Entonces es útil deshabilitar completamente el procesamiento por lotes.