¿Hay alguna manera de volcar un seguimiento de pila sin lanzar una excepción en Java?


Estoy pensando en crear una herramienta de depuración para mi aplicación Java.

Me pregunto si es posible obtener un seguimiento de pila, al igual que Exception.printStackTrace() pero sin lanzar una excepción.

Mi objetivo es, en cualquier método dado, volcar una pila para ver quién es el método que llama.

Author: bruno, 2009-06-03

9 answers

También puede intentar Thread.getAllStackTraces() obtener un mapa de trazas de pila para todos los hilos que están vivos.​​​​​​

 70
Author: Ram,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-04-09 09:14:23

Sí, simplemente use

Thread.dumpStack()
 190
Author: Rob Di Marco,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-06-03 14:17:19

Si desea el seguimiento solo para el subproceso actual (en lugar de todos los subprocesos en el sistema, como lo hace la sugerencia de Ram), haga:

Hilo.currentThread(). getStackTrace()

Para encontrar al llamante, haga:

private String getCallingMethodName() {
    StackTraceElement callingFrame = Thread.currentThread().getStackTrace()[4];
    return callingFrame.getMethodName();
}

Y llama a ese método desde dentro del método que necesita saber quién es su llamante. Sin embargo, una palabra de advertencia: el índice del marco de llamada dentro de la lista podría variar de acuerdo con la JVM! Todo depende de cuántas capas de llamadas hay dentro getStackTrace antes de llegar al punto donde se genera la traza. Una solución más robusta sería obtener el seguimiento, e iterar sobre él buscando el marco para getCallingMethodName, luego dar dos pasos más para encontrar el verdadero llamador.

 34
Author: Tom Anderson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-06-04 10:23:38

Puede obtener un seguimiento de pila como este:

Throwable t = new Throwable();
t.printStackTrace();

Si desea acceder al marco, puede usar t.getStackTrace() para obtener una matriz de marcos de pila.

Tenga en cuenta que este stacktrace (al igual que cualquier otro) puede estar faltando algunos marcos si el compilador de hotspot ha estado ocupado optimizando cosas.

 27
Author: Gerco Dries,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-06-03 14:16:12

Observe ese hilo.dumpStack () en realidad lanza una excepción:

new Exception("Stack trace").printStackTrace();
 11
Author: Ariel T,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-01-31 15:06:20

También puede enviar una señal a la JVM para ejecutar el subproceso.getAllStackTraces () en un proceso Java en ejecución enviando una señal de SALIDA al proceso.

En Unix / Linux uso:

kill -QUIT process_id, donde process_id es el número de proceso de su programa Java.

En Windows, puede presionar Ctrl-Break en la aplicación, aunque generalmente no verá esto a menos que esté ejecutando un proceso de consola.

JDK6 introdujo otra opción, el comando jstack, que mostrará la pila desde cualquier proceso JDK6 en ejecución en su computadora:

jstack [-l] <pid>

Estas opciones son muy útiles para aplicaciones que se ejecutan en un entorno de producción y no se pueden modificar fácilmente. Son especialmente útiles para diagnosticar bloqueos en tiempo de ejecución o problemas de rendimiento.

Http://java.sun.com/developer/technicalArticles/Programming/Stacktrace / http://java.sun.com/javase/6/docs/technotes/tools/share/jstack.html

 6
Author: Andrew Newdigate,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-06-03 16:04:38

Si necesita capturar la salida

StringWriter sw = new StringWriter();
new Throwable("").printStackTrace(new PrintWriter(sw));
String stackTrace = sw.toString();
 3
Author: Ricardo Jl Rufino,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-04-04 10:50:27

Java 9 introdujo el StackWalker y clases de apoyo para caminar por la pila.

Aquí hay algunos fragmentos del Javadoc:

El walk método abre un flujo secuencial de StackFrames para el hilo actual y luego aplica la función dada para recorrer el flujo StackFrame. La secuencia informa de los elementos del marco de pila en orden, desde el marco superior que representa el punto de ejecución en el que se generó la pila hasta el marco inferior. El StackFrame la secuencia se cierra cuando regresa el método walk. Si se intenta reutilizar la secuencia cerrada, se lanzará IllegalStateException.

...

  1. Para capturar los 10 marcos de pila superiores del subproceso actual,

    List<StackFrame> stack = StackWalker.getInstance().walk(s ->
     s.limit(10).collect(Collectors.toList()));
    
 2
Author: mkobit,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-07 14:16:03

HPROF Java Profiler

Ni siquiera tienes que hacer esto en el código. Puede adjuntar el Java HPROF a su proceso y en cualquier punto hit Control - \ a salida heap dump, subprocesos en ejecución, etc. . . sin estropear el código de su aplicación. Esto es un poco anticuado, Java 6 viene con la interfaz gráfica de usuario jconsole, pero todavía encuentro HPROF para ser muy útil.

 0
Author: Gandalf,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-30 15:00:28