C'est probablement une question très naïve.
J'avais l'habitude de croire qu'un Throwable
dans Java
toujours contient la trace de la pile. Est-ce correct? Maintenant, il semble que j'attrape exceptions
sans la trace de la pile. Est-ce que ça fait du sens? Est-ce possible pour intercepter une exception sans la trace de pile?
Il est possible d'attraper un objet Throwable dans Java sans trace de pile:
Throwable(String message, Throwable cause, boolean enableSuppression,boolean writableStackTrace)
Construit un nouveau fichier jetable avec le message de détail spécifié, la cause, la suppression activée ou désactivée et la trace de pile accessible en écriture activée ou désactivée.
http://docs.Oracle.com/javase/7/docs/api/Java/lang/Throwable.html
Pour Java 6:
Comme Java 6 n'a pas le constructeur Throwable(String message, Throwable cause, boolean enableSuppression,boolean writableStackTrace)
, nous pouvons supprimer le remplissage de stacktrace en utilisant la technique ci-dessous (emprunté à Scala, appris depuis à quelle vitesse sont Java exceptions? )
class NoStackTraceRuntimeException extends RuntimeException {
@Override
public synchronized Throwable fillInStackTrace() {
return this;
}
}
L'utilisation est la même: throw new NoStackTraceRuntimeException ()
, ou ses sous-types.
Nous pouvons également faire de même en étendant Throwable
:
class NoStackTraceThrowable extends Throwable {
@Override
public synchronized Throwable fillInStackTrace() {
return this;
}
}
Mais, un petit hic, c'est que vous ne pouvez plus catch
ces exceptions en utilisant Exception
car ce n'est pas un sous-type de Exception
, vous devriez plutôt attraper NoStackTraceThrowable
ou c'est sous-types.
Mise à jour : Pour des statistiques intéressantes sur les performances dans différents cas d'utilisation, vérifiez ceci SO question
Pour Java 7+, voici un exemple d'une exception où la trace de pile peut éventuellement être supprimée.
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();
}
}
}
Cela peut être démontré avec:
try {
throw new SuppressableStacktraceException("Not suppressed", false);
} catch (SuppressableStacktraceException e) {
e.printStackTrace();
}
try {
throw new SuppressableStacktraceException("Suppressed", true);
} catch (SuppressableStacktraceException e) {
e.printStackTrace();
}
Ceci est basé sur l'exception MLContextException de Apache SystemML , dont le code est disponible sur GitHub à https://github.com/Apache/systemml .
La façon la plus simple de supprimer la trace de pile sur toute exception est
throwable.setStackTrace(new StackTraceElement[0]);
Si l'exception a une cause, vous devrez peut-être faire de même récursivement.
Cela réduit également autant que possible la création coûteuse de la trace de pile
La trace de pile pour un jetable est initialisée dans
Throwable#fillInStackTrace()
, qui est appelé par n'importe quel constructeur et ne peut donc pas être évité. Lorsque le stacktrace est réellement utilisé, un StackTraceElement [] est construit paresseusement dans
Throwable#getOurStackTrace()
ce qui ne se produit que si le champ Throwable.stackTrace n'était pas déjà défini.
La définition de stacktrace sur une valeur non nulle, évite la construction de StackTraceElement [] dans Throwable # getOurStackTrace () et réduit autant que possible la baisse des performances.