Como posso obter o rastreamento de pilha atual em Java?


1002

Como obtenho o rastreamento de pilha atual em Java, como no .NET você pode fazer Environment.StackTrace?

Encontrei, Thread.dumpStack()mas não é o que eu quero - quero recuperar o rastreio da pilha, não imprimi-lo.


73
Eu sempre uso "new Exception (). PrintStackTrace ()" como uma expressão de observação quando estou depurando no Eclipse. Isso é útil quando você suspende em um ponto de interrupção e deseja saber de onde você veio.
217 Tim Timeley

22
@ TimBüthe: o Eclipse já não está dizendo o Rastreamento de Pilha quando você está no modo de depuração? Acho que sim.
Luigi Massa Gallerano 9/08/13

41
Arrays.toString (Thread.currentThread (). GetStackTrace ()); simples o suficiente.
quer

2
@Arkanon Refere-se a java, e está mostrando como eles o fariam em .net e qual é o equivalente em java.
Pokechu22

9
Para imprimir bem, você pode usar o apache StringUtils: StringUtils.join (currentThread (). GetStackTrace (), "\ n");
Art

Respostas:


1159

Você pode usar Thread.currentThread().getStackTrace().

Isso retorna uma matriz de StackTraceElements que representa o rastreamento de pilha atual de um programa.


48
Um fresco de uma linha se você já está usando Apache commons para obter uma string: String fullStackTrace = org.apache.commons.lang.exception.ExceptionUtils.getFullStackTrace(e); stackoverflow.com/a/10620951/11236
ripper234

5
O primeiro elemento (índice 0) na matriz é o método java.lang.Thread.getStackTrace, o segundo (índice 1) geralmente é o primeiro de interesse.
lilalinux

175
Um um forro para converter o rastreamento de pilha para uma cadeia que funciona quando você não tem uma exceção e você não está usando Apache Arrays.toString (Thread.currentThread () getStackTrace ().)
Tony

9
A solução da @Tony é melhor porque não requer um lançamento
mvd

3
Como apontado em muitas respostas abaixo - o new Throwable().getStackTrace()é muito mais rápido, porque ele não precisa verificar this != Thread.currentThread()e ignora potenciais despesas gerais JVM de chamá-lo através de classe criança ( Exception extends Throwable)
Vlad

265
Thread.currentThread().getStackTrace();

é bom se você não se importa qual é o primeiro elemento da pilha.

new Throwable().getStackTrace();

terá uma posição definida para o seu método atual, se isso interessar.


35
(new Throwable()).getStackTrace()também está executando mais rapidamente (consulte bugs.sun.com/bugdatabase/view_bug.do?bug_id=6375302 )
MightyE

2
Você pode explicar com mais detalhes como os resultados de Thread.currentThread (). GetStackTrace () podem ser diferentes de new Throwable (). GetStackTrace ()? Tentei os dois e descobri que Thread.currentThread (). GetStackTrace () retorna uma matriz com Thread.getStackTrace no índice 0 e o método de chamada está no índice 1. O novo método Throwable (). GetStackTrace () retorna uma matriz com a chamada método no índice 0. Parece que os dois métodos têm uma posição definida para o método atual, mas as posições são diferentes. Há outra diferença que você está apontando?
21713 Ryan

9
@ Ryan, não há garantia de que Thread.currentThread (). GetStackTrace () não prometa manter essa posição em diferentes versões do método. Então, quando você verificou que estava no índice 1. Em algumas versões da JVM (1.5 ou 1.6, não se lembra) da Sun, era o índice 2. Isso é o que quero dizer com uma posição definida - a especificação exige estar lá e permanecer lá no futuro.
Yishai

5
@MightyE O bug agora é relatado como fechado como corrigido no Java 6. Observando as partes internas, parece que agora ocorre (new Exception()).getStackTrace()quando o rastreamento de pilha solicitado está no encadeamento atual (o que sempre será o caso paraThread.currentThread().getStackTrace();
M. Justin

3
@MJustin: o bug não é "agora" relatado como corrigido, foi corrigido mesmo seis anos antes de o MightyE escrever o comentário. De fato, ele foi corrigido antes mesmo de o Stackoverflow ser fundado ...
Holger

181
for (StackTraceElement ste : Thread.currentThread().getStackTrace()) {
    System.out.println(ste);
}

20
java tem um método printStackTrace definido em Throwable, você pode fazer: new Exception().printStackTrace(System.out)que me lembro, o loop for, provavelmente tem menos sobrecarga, mas você só deve usar isso como uma coisa depuração de qualquer maneira ...
Jaap

2
I como este melhor porque você tem a chance de retirar ruído, envolvendo sua declaração println, por exemplofor (StackTraceElement ste : Thread.currentThread().getStackTrace()) { if(ste.toString().contains("mypackages")){ System.out.println(ste); } }
npor

61
Thread.currentThread().getStackTrace();

está disponível desde o JDK1.5.

Para uma versão mais antiga, você pode redirecionar exception.printStackTrace()para StringWriter():

StringWriter sw = new StringWriter();
new Throwable("").printStackTrace(new PrintWriter(sw));
String stackTrace = sw.toString();

3
new Throwable().getStackTrace()está disponível desde JDK1.4…
Holger

40

Você pode usar os recursos comuns do Apache para isso:

String fullStackTrace = org.apache.commons.lang3.exception.ExceptionUtils.getStackTrace(e);

13
Esta é uma ótima solução de uma linha. Para sua informação, para quem está usando org.apache.commons.lang3, a linha completa é:org.apache.commons.lang3.exception.ExceptionUtils.getStackTrace(e);
fileoffset 26/07

2
Apenas para reiterar o comentário do fileoffset ao mudar para org.apache.commons.lang3, o qual eu inicialmente ignorei - a importação usa em lang3vez de lange substitui getFullStackTracepor getStackTrace.
ggkmath

Isso é muito útil! Ao depurar usando um IDE (por exemplo, IntelliJ IDEA), é ótimo usar a ExceptionUtils.getStackTrace(new Throwable())expressão para obter o rastreamento de pilha.
Sergey Brunov 21/02/19


22

Para obter o rastreio da pilha de todos os encadeamentos, você pode usar o utilitário jstack, JConsole, ou enviar um sinal de kill-quit (em um sistema operacional Posix).

No entanto, se você quiser fazer isso programaticamente, tente usar o ThreadMXBean:

ThreadMXBean bean = ManagementFactory.getThreadMXBean();
ThreadInfo[] infos = bean.dumpAllThreads(true, true);

for (ThreadInfo info : infos) {
  StackTraceElement[] elems = info.getStackTrace();
  // Print out elements, etc.
}

Como mencionado, se você deseja apenas o rastreamento de pilha do encadeamento atual, é muito mais fácil - basta usar Thread.currentThread().getStackTrace();


2
O trecho de código nesta resposta é o mais próximo de gerar programaticamente o tipo de despejo que você vê ao enviar à JVM o sinal QUIT (em sistemas como Unix) ou <ctrl> <break> no Windows. Ao contrário das outras respostas, você vê monitores e sincronizadores, bem como apenas os rastreamentos de pilha (por exemplo, se você iterar sobre a matriz StackTraceElement e executar System.err.println(elems[i])em cada um). A segunda linha do trecho está faltando bean.antes do, dumpAllThreadsmas acho que a maioria das pessoas poderia resolver isso.
George Hawkins

22

Outra solução (apenas 35 31 caracteres):

new Exception().printStackTrace();   
new Error().printStackTrace();

1
solução incrível. Agora eu não tenho que percorrer todos os quadros de pilha
Vineel Kovvuri


17

Tony, como comentário à resposta aceita, deu a que parece ser a melhor resposta que realmente responde à pergunta do OP :

Arrays.toString(Thread.currentThread().getStackTrace()).replace( ',', '\n' );

... o OP NÃO perguntou como obter um Stringdo rastreamento de pilha de um Exception. E embora eu seja um grande fã do Apache Commons, quando há algo tão simples quanto o descrito acima, não há razão lógica para usar uma biblioteca externa.


Eu tenho uma lista de threads e preciso imprimir seus rastreamentos de pilha.
Daneel S. Yaitskov

Nesse caso, certifique-se de usar o Thread.getAllStackTraces()que lhe dá a Map<Thread, StackTraceElement[]>. O ponto de acesso apontará com segurança todos os threads sempre que precisar apontar com segurança um. O Zing pode levar segmentos individuais a um ponto seguro sem incomodar o outro. Obter um rastreamento de pilha requer um ponto seguro. Thread.getAllStackTraces()obtém todos os rastreamentos de pilha e para todos os threads apenas uma vez. Obviamente, você deve descobrir em qual mapeamento você realmente está interessado.
Ralf H

14

Eu sugiro que

  Thread.dumpStack()

é uma maneira mais fácil e tem a vantagem de não criar uma exceção ou uma ação de lançar quando não pode haver nenhum problema e é consideravelmente mais direto ao ponto.


1
Ok, na verdade, o dumpStack () é um método estático e deve ser acessado de maneira estática. Obrigado, eclipse!
Thomas Adkins

1
Eu amo o atalho, mas o código fonte para este método é: new Exception("Stack trace").printStackTrace();por isso é realmente construir um Throwable
Florent

13

Obtendo o stacktrace:

StackTraceElement[] ste = Thread.currentThread().getStackTrace();

Rastreio de pilha de impressão (JAVA 8+):

Arrays.asList(ste).forEach(System.out::println);

Stacktrage de impressão (JAVA 7):

StringBuilder sb = new StringBuilder();

for (StackTraceElement st : ste) {
    sb.append(st.toString() + System.lineSeparator());
}
System.out.println(sb);

12

No Java 9, há uma nova maneira:

public static void showTrace() {

  List<StackFrame> frames =
    StackWalker.getInstance( Option.RETAIN_CLASS_REFERENCE )
               .walk( stream  -> stream.collect( Collectors.toList() ) );

  for ( StackFrame stackFrame : frames )
    System.out.println( stackFrame );
}

Interessante. :-)
djangofan 20/02

10

Eu tenho um método utilitário que retorna uma seqüência de caracteres com o stacktrace:

static String getStackTrace(Throwable t) {
    StringWriter sw = new StringWriter();
    PrintWriter pw = new PrintWriter(sw, true);
    t.printStackTrace(pw);
    pw.flush();
    sw.flush();
    return sw.toString();
}

E apenas logit como ...

... 
catch (FileNotFoundException e) {
    logger.config(getStackTrace(e));
}

Parece um auto gerado pelo Netbeans.
Leif Gruenwoldt 12/09

é um criador de logs incorporado ou que você criou e grava em um arquivo.
Doug Hauf 15/02

@Doug Hauf, logger é uma referência ao Java Logger embutido. Certifique-se de configurar o arquivo logging.properties. Adicione-o no início da sua classe desta maneira: private static final Logger logger = Logger.getLogger (Your_Class_Name.class.getName ());
Salvador Valencia

1
java.util.logging.Logger#log(Level, String, Throwable)já faz isso. Isso está reescrevendo coisas que já existem na biblioteca padrão Java desnecessariamente e está apontando novos desenvolvedores na direção errada, o que está longe da documentação. Ao fazer isso agora, você forçou o Stacktrace a ser formatado de uma certa maneira, onde a loggingAPI permite variar a formatação da instrução de log dinamicamente conforme você a especifica. Que eu saiba, log4jtambém tem um comportamento semelhante. Não reinvente a roda porque você acaba perdendo coisas como eu expliquei.
usar o seguinte

1
Também existia em 2012. Infelizmente, a data não faz diferença no seu caso. Consulte [link] (docs.oracle.com/javase/1.5.0/docs/api/java/util/logging/Logger.html#log (java.util.logging.Level, java.lang.String, java.lang .Throwable)), [link] (docs.oracle.com/javase/1.5.0/docs/api/java/util/logging/Logger.html#log (java.util.logging.LogRecord)), etc. (existem existem várias funções que passam Throwablede Handlers para Formatters em 2012, que era Java7, mais do que eu listei aqui.E essas funções datam de muito mais tempo que o Java7 existe; daí o J2SE 5.0 javadocs)
searchengine27

10

Para string com goiaba:

Throwables.getStackTraceAsString(new Throwable())

8
try {
}
catch(Exception e) {
    StackTraceElement[] traceElements = e.getStackTrace();
    //...
}

ou

Thread.currentThread().getStackTrace()

Seu exemplo principal não fornecerá apenas o rastreamento da pilha em relação ao bloco try / catch?
Dan Dan

1
Qual é a diferença entre os dois
twlkyao

5

Talvez você possa tentar o seguinte:

catch(Exception e)
{
    StringWriter writer = new StringWriter();
    PrintWriter pw = new PrintWriter(writer);
    e.printStackTrace(pw);
    String errorDetail = writer.toString();
}

A sequência 'errorDetail' contém o rastreamento de pilha.


5
StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();

O último elemento da matriz representa a parte inferior da pilha, que é a invocação de método menos recente na sequência.

A StackTraceElement has getClassName(), getFileName(), getLineNumber() and getMethodName().

percorrer StackTraceElement e obter o resultado desejado.

for (StackTraceElement ste : stackTraceElements ) 
{
    //do your stuff here...
}

Obrigado por mencionar o último elemento que contém o mais recente. Contra-intuitivo e me salvou algum tempo.
Clearlight 16/08/2015

Também .ToString saída vontade () todos os dados muito bem em uma corda
Vlad

4

Usei as respostas acima e adicionei formatação

public final class DebugUtil {

    private static final String SEPARATOR = "\n";

    private DebugUtil() {
    }

    public static String formatStackTrace(StackTraceElement[] stackTrace) {
        StringBuilder buffer = new StringBuilder();
        for (StackTraceElement element : stackTrace) {
            buffer.append(element).append(SEPARATOR);
        }
        return buffer.toString();
    }

    public static String formatCurrentStacktrace() {
        StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
        return formatStackTrace(stackTrace);
    }
}

2

Você pode usar o utilitário jstack se quiser verificar a pilha de chamadas atual do seu processo.

Usage:
    jstack [-l] <pid>
        (to connect to running process)
    jstack -F [-m] [-l] <pid>
        (to connect to a hung process)
    jstack [-m] [-l] <executable> <core>
        (to connect to a core file)
    jstack [-m] [-l] [server_id@]<remote server IP or hostname>
        (to connect to a remote debug server)

Options:
    -F  to force a thread dump. Use when jstack <pid> does not respond (process is hung)
    -m  to print both java and native frames (mixed mode)
    -l  long listing. Prints additional information about locks
    -h or -help to print this help message

1

Este é um post antigo, mas aqui está a minha solução:

Thread.currentThread().dumpStack();

Mais informações e mais métodos lá: http://javarevisited.blogspot.fr/2013/04/how-to-get-current-stack-trace-in-java-thread.html


3
Como Thread.dumpStack () é estático, você deve chamá-lo diretamente.
9306 David Avendasora #

2
O OP indicou que deseja uma referência no código para o rastreamento da pilha, para não imprimi-lo.
Taylor R

1
como o @DavidAvendasora mencionou, você deve ligar Thread.dumpStack()diretamente porque é um método estático.
M-Wajeeh

Sim, java.lang.Thread.dumpStack () funciona no Java 11.
Park JongBum

-3

System.out.println(Arrays.toString(Thread.currentThread().getStackTrace()));

Isso ajudará você a imprimir o rastreamento de pilha sem loop.


1
Sua resposta é a mesma que a minha postada 3 meses antes.
mike roedor
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.