Excepción sin seguimiento de pila en Java

5 minutos de lectura

avatar de usuario
Miguel

Esta es probablemente una pregunta muy ingenua.

Solía ​​creer que un Throwable en Java siempre contiene el seguimiento de la pila. ¿Es correcto?

Ahora parece que atrapo excepciones sin que el rastro de la pila. ¿Tiene sentido? Lo es posible capturar una excepción sin el seguimiento de la pila?

  • ¿Qué JVM? ¿Ambiente? etc. ¿Esto ayuda? stackoverflow.com/questions/4659151/…

    – NG.

    11 de julio de 2012 a las 14:07

  • @SB. Sí, esto ayuda. Muchas gracias. Tengo un problema muy similar: tengo muchas excepciones (NPE). Método error de log4j registra algunas excepciones sin que el rastro de la pila.

    – Miguel

    11 de julio de 2012 a las 14:25


avatar de usuario
alex w

Es posible atrapar un objeto Throwable en Java sin un seguimiento de pila:

Throwable(String message, Throwable cause, boolean enableSuppression,boolean writableStackTrace) 

Construye un nuevo lanzamiento con el mensaje de detalle especificado, la causa, la supresión habilitada o deshabilitada, y
rastreo de pila grabable habilitado o deshabilitado.

public Throwable fillInStackTrace()

Rellena el seguimiento de la pila de ejecución. Este método registra dentro de este objeto Throwable información sobre el estado actual de los marcos de pila para el subproceso actual.

Si el seguimiento de la pila de este Throwable no se puede escribir, llamar a este método no tiene ningún efecto..

http://docs.oracle.com/javase/7/docs/api/java/lang/Throwable.html

  • Simplemente dice “seguimiento de pila grabable” habilitado o deshabilitado. No creo que signifique que no detectará el seguimiento de pila

    – MatanCo

    19 de junio de 2019 a las 9:18

  • ¿Significa esto que no se generará y el proceso será mucho más rápido?

    – Pablo

    16 oct 2019 a las 9:33

  • la documentación para writableStackTrace dice esto: “si el seguimiento de la pila debe o no ser escribible“. Por lo tanto, ese parámetro NO evita que se generen rastros de pila. No veo cómo esta publicación responde a la pregunta. ¡Corrija o elimine esta respuesta!

    – Lii

    1 de abril de 2020 a las 11:52


  • Por favor, lea la pregunta. OP pregunta si es posible atrapar un Throwable sin rastro de pila. La respuesta es, por supuesto, sí. Cita directa de la documentación para fillInStackTrace: “Rellena el seguimiento de la pila de ejecución. Este método registra dentro de este objeto Throwable información sobre el estado actual de los marcos de la pila para el subproceso actual. Si no se puede escribir en el seguimiento de la pila de este Throwable, llamar a este método no tiene efecto”.

    – Alex W.

    15 mayo 2020 a las 17:47

avatar de usuario
manikanta

Para Java 6:

Como Java 6 no tiene la Throwable(String message, Throwable cause, boolean enableSuppression,boolean writableStackTrace) constructor, podemos suprimir el llenado de stacktrace utilizando la siguiente técnica (tomada de Scala, aprendida de ¿Qué tan lentas son las excepciones de Java?)

class NoStackTraceRuntimeException extends RuntimeException {
    @Override
    public synchronized Throwable fillInStackTrace() {
        return this;
    }
}

El uso es el mismo: throw new NoStackTraceRuntimeException ()o sus subtipos.

También podemos hacer lo mismo extendiendo Throwable:

class NoStackTraceThrowable extends Throwable {
    @Override
    public synchronized Throwable fillInStackTrace() {
        return this;
    }
}

Pero, una pequeña pega es que ya no puedes catch estas excepciones usando Exception ya que este no es un subtipo de Exceptionen su lugar debería atrapar NoStackTraceThrowable o sus subtipos.

Actualizar: Para obtener algunas estadísticas interesantes sobre el rendimiento en diferentes casos de uso, consulte esta pregunta SO

  • @shekharsuman No, pero tampoco Java 7. Esta respuesta podría ayudar a alguien con Java 6 🙂

    – manikanta

    15 de agosto de 2014 a las 10:09

  • Incluso fuera de Java 1.6, este sigue siendo un método viable. Esto suprimirá todo el seguimiento de la pila (ya que se imprimirá la ‘causa’ pasada del constructor de 4 parámetros).

    – DBK

    8 mayo 2015 a las 13:17

  • Todavía estoy usando Java 6 aquí en 2016, así que sí:/

    – Carlos Madera

    23 de marzo de 2016 a las 22:01

  • Su NoStackTraceThrowable podría extenderse Exception en cambio (y ser llamado NoStackTraceException) si querías que fuera atrapado por un catch (Exception) bloquear.

    – dimo414

    03/04/2016 a las 17:11

  • No hay necesidad de marcar un método simplemente regresando this como synchronized.

    – Holger

    1 de noviembre de 2019 a las 16:33

avatar de usuario
Deron

Para Java 7+, aquí hay un ejemplo de una excepción donde el seguimiento de la pila se puede suprimir opcionalmente.

public class SuppressableStacktraceException extends Exception {

    private boolean suppressStacktrace = false;

    public SuppressableStacktraceException(String message, boolean suppressStacktrace) {
        super(message, null, suppressStacktrace, !suppressStacktrace);
        this.suppressStacktrace = suppressStacktrace;
    }

    @Override
    public String toString() {
        if (suppressStacktrace) {
            return getLocalizedMessage();
        } else {
            return super.toString();
        }
    }
}

Esto se puede demostrar con:

try {
    throw new SuppressableStacktraceException("Not suppressed", false);
} catch (SuppressableStacktraceException e) {
    e.printStackTrace();
}
try {
    throw new SuppressableStacktraceException("Suppressed", true);
} catch (SuppressableStacktraceException e) {
    e.printStackTrace();
}

Esto se basa en la MLContextException de Sistema ApacheMLcuyo código está disponible en GitHub en https://github.com/apache/systemml.

  • Claro, eliminar toString() todavía me proporciona suficiente supresión.

    – Benny Bottema

    9 de octubre de 2019 a las 9:16

  • ¿Por qué no estás exponiendo un argumento de constructor que tomaría un arrojable?

    – Ihor M.

    16 dic 2019 a las 21:10

  • ¿Por qué supressStackTrace implica un argumento supressedException en Exception?

    – Caprichoso

    21 de abril de 2020 a las 11:00

  • ¿Por qué necesita anular toString?

    – JojOatXGME

    26 de mayo de 2021 a las 9:40

avatar de usuario
Stefan Isele – prefabware.com

La forma más fácil de suprimir el seguimiento de la pila en cualquier excepción es

throwable.setStackTrace(new StackTraceElement[0]);

Si la excepción tiene una causa, es posible que deba hacer lo mismo de forma recursiva.

Esto también reduce la costosa creación del seguimiento de la pila, tanto como sea posible.

El stacktrace para un throwable se inicializa en

Throwable#fillInStackTrace()

, que es llamado por cualquier constructor y, por lo tanto, no se puede evitar. Cuando realmente se usa stacktrace, un StackTraceElement[] está perezosamente construido en

Throwable#getOurStackTrace()

lo que solo sucede si el campo Throwable.stackTrace no estaba ya configurado.

Establecer stacktrace en cualquier valor no nulo evita la construcción de StackTraceElement[] en Throwable#getOurStackTrace() y reduce la penalización de rendimiento tanto como sea posible.

Como se insinuó en la respuesta de NG., si está viendo el seguimiento de pila al principio pero luego desaparece por la misma excepción, lo más probable es que esté viendo los efectos de la optimización de JVM. En ese caso, las siguientes preguntas son muy similares.

Excepción recurrente sin seguimiento de pila: ¿cómo restablecer?

NullPointerException en Java sin StackTrace

Puede desactivar esta característica de JVM, pero recomendaría mantenerla habilitada y trabajar para prevenir el error en primer lugar, o detectarlo y manejarlo con más gracia.

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad