java - print - stack trace que es
¿Cómo impido que stacktraces trunque en los registros? (5)
Apache''s Commons Lang proporciona un buen método util ExceptionUtils.printRootCauseStackTrace() que imprime un stacktrace anidado ''al revés''. El resultado es mucho más intuitivo.
Si ve el resultado junto al original fuera del método printStackTrace (), quedará claro dónde fueron las "113 líneas más".
Muchas veces en los registros de Java obtendré algo así 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 la pila completa (es decir, mostrar las otras 113 líneas)?
Los JavaDocs (para Java 7) para Throwable tienen una explicación bastante detallada de lo que está sucediendo.
Aumentar -XX:MaxJavaStackTraceDepth
Opción JVM.
Cuando vea ''... 113 more'', 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 padre.
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>.
Los dos rastreos de la pila ''se encuentran'' en AbstractBatcher.exeBuiltBatch, línea 242 y, a partir de ese momento, el rastreo de la llamada ascendente es igual a la excepción de ajuste.
En una publicación de blog, describí cómo obtener más que solo "BatchUpdateException: failed batch" : configure hibernate.jdbc.factory_class=org.hibernate.jdbc.NonBatchingBatcherFactory
para deshabilitar el procesamiento por lotes en hibernación. Normalmente uno puede usar BatchUpdateException.getNextException
para obtener el motivo de la falla, pero en algunos casos esto puede devolver null
. Entonces es útil deshabilitar el procesamiento por lotes por completo.
Me gusta el ejemplo que se encuentra 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, las llamadas main
function a
que llama a la function b
que llama ... que llama a la function e
. Function e
arroja una LowLevelException
que hace que la función c capture la LowLevelException
y arroje una MidLevelException
(envolviendo la instancia de LowLevelException
dentro de la instancia de MidLevelException
. La clase Exception
tiene un constructor que es capaz de aceptar una excepción diferente, envolviéndola). Esto hace que la función a capte la MidLevelException
y arroje una HighLevelException
que ahora envuelve las dos instancias de Exception
anteriores.
Como se señala 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 sería redundante de lo contrario. Si quisiera ser redundante y desperdicie líneas de salida, .. 3 more
podrían reemplazarse .. 3 more
con
at Junk.b(Junk.java:17)
at Junk.a(Junk.java:11)
at Junk.main(Junk.java:4)
Pero no es necesario dar salida a estas tres líneas, porque ya están implícitas.