Comment imprimer les numéros de ligne dans le journal. Dites, lors de la sortie de certaines informations dans le journal, que je veux aussi imprimer le numéro de ligne où cette sortie est dans le code source. Comme on peut le voir dans la trace de la pile, il affiche le numéro de la ligne où l'exception s'est produite. La trace de pile est disponible sur l'objet exception.
Une autre solution pourrait consister à inclure manuellement le numéro de ligne lors de l’impression dans le journal. Y-a t'il une autre possibilité?
De Angsuman Chakraborty :
/** Get the current line number.
* @return int - Current line number.
*/
public static int getLineNumber() {
return Thread.currentThread().getStackTrace()[2].getLineNumber();
}
Nous avons fini par utiliser une classe personnalisée comme celle-ci pour notre travail sur Android:
import Android.util.Log;
public class DebugLog {
public final static boolean DEBUG = true;
public static void log(String message) {
if (DEBUG) {
String fullClassName = Thread.currentThread().getStackTrace()[2].getClassName();
String className = fullClassName.substring(fullClassName.lastIndexOf(".") + 1);
String methodName = Thread.currentThread().getStackTrace()[2].getMethodName();
int lineNumber = Thread.currentThread().getStackTrace()[2].getLineNumber();
Log.d(className + "." + methodName + "():" + lineNumber, message);
}
}
}
Manière rapide et sale:
System.out.println("I'm in line #" +
new Exception().getStackTrace()[0].getLineNumber());
Avec quelques détails supplémentaires:
StackTraceElement l = new Exception().getStackTrace()[0];
System.out.println(
l.getClassName()+"/"+l.getMethodName()+":"+l.getLineNumber());
Cela produira quelque chose comme ceci:
com.example.mytest.MyClass/myMethod:103
Je suis obligé de répondre en ne répondant pas à votre question. Je suppose que vous recherchez le numéro de ligne uniquement pour prendre en charge le débogage. Il y a de meilleures façons. Il y a des façons détournées d'obtenir la ligne actuelle. Tout ce que j'ai vu est lent. Vous feriez mieux d'utiliser un cadre de journalisation tel que celui du package Java.util.logging ou log4j . À l'aide de ces packages, vous pouvez configurer vos informations de journalisation pour inclure le contexte jusqu'au nom de la classe. Chaque message de journalisation serait alors suffisamment unique pour savoir d’où il venait. En conséquence, votre code aura une variable 'logger' que vous appelez via
logger.debug("a really descriptive message")
au lieu de
System.out.println("a really descriptive message")
Log4J vous permet d'inclure le numéro de ligne dans le modèle de sortie. Voir http://logging.Apache.org/log4j/1.2/apidocs/org/Apache/log4j/PatternLayout.html pour plus d'informations sur la procédure à suivre (l'élément clé du modèle de conversion est "L"). . Cependant, la Javadoc comprend les éléments suivants:
AVERTISSEMENT Génération de la localisation de l'appelant l'information est extrêmement lente. Ses utilisation doit être évitée sauf si exécution la vitesse n'est pas un problème.
J'utilise cette petite méthode qui affiche le numéro de trace et le numéro de ligne de la méthode qui l'a appelée.
Log.d(TAG, "Where did i put this debug code again? " + Utils.lineOut());
Double-cliquez sur la sortie pour accéder à cette ligne de code source!
Vous devrez peut-être ajuster la valeur du niveau en fonction de l'emplacement de votre code.
public static String lineOut() {
int level = 3;
StackTraceElement[] traces;
traces = Thread.currentThread().getStackTrace();
return (" at " + traces[level] + " " );
}
Le code posté par @ simon.buchan fonctionnera ...
Thread.currentThread().getStackTrace()[2].getLineNumber()
Mais si vous l'appelez dans une méthode, elle renverra toujours le numéro de ligne de la ligne dans la méthode, utilisez plutôt l'extrait de code en ligne.
Je recommanderais d'utiliser une boîte à outils de journalisation telle que log4j . La journalisation est configurable via des fichiers de propriétés au moment de l'exécution, et vous pouvez activer/désactiver des fonctionnalités telles que la journalisation du numéro de ligne/nom de fichier.
En regardant le javadoc pour le PatternLayout vous donne la liste complète des options - ce que vous voulez, c'est% L.
La stackLevel
dépend de la profondeur à laquelle vous appelez cette méthode. Vous pouvez essayer de 0 à un grand nombre pour voir quelle différence.
Si stackLevel
est légal, vous aurez une chaîne comme Java.lang.Thread.getStackTrace(Thread.Java:1536)
public static String getCodeLocationInfo(int stackLevel) {
StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
if (stackLevel < 0 || stackLevel >= stackTraceElements.length) {
return "Stack Level Out Of StackTrace Bounds";
}
StackTraceElement stackTraceElement = stackTraceElements[stackLevel];
String fullClassName = stackTraceElement.getClassName();
String methodName = stackTraceElement.getMethodName();
String fileName = stackTraceElement.getFileName();
int lineNumber = stackTraceElement.getLineNumber();
return String.format("%s.%s(%s:%s)", fullClassName, methodName, fileName, lineNumber);
}
C’est exactement la fonctionnalité que j’ai implémentée dans cette lib XDDLib . (Mais c'est pour Android)
Lg.d("int array:", intArrayOf(1, 2, 3), "int list:", listOf(4, 5, 6))
Un clic sur le texte souligné pour accéder à l'emplacement de la commande log
Ce StackTraceElement
est déterminé par le premier élément situé en dehors de cette bibliothèque. Ainsi, n'importe où en dehors de cette bibliothèque sera légal, y compris lambda expression
, static initialization block
, etc.
Regardez ce lien . Avec cette méthode, vous pouvez accéder à votre code de ligne en double-cliquant sur la ligne de LogCat.
Aussi, vous pouvez utiliser ce code pour obtenir le numéro de ligne:
public static int getLineNumber()
{
int lineNumber = 0;
StackTraceElement[] stackTraceElement = Thread.currentThread()
.getStackTrace();
int currentIndex = -1;
for (int i = 0; i < stackTraceElement.length; i++) {
if (stackTraceElement[i].getMethodName().compareTo("getLineNumber") == 0)
{
currentIndex = i + 1;
break;
}
}
lineNumber = stackTraceElement[currentIndex].getLineNumber();
return lineNumber;
}
Voici l'enregistreur que nous utilisons.
il englobe Android Logger et le nom de la classe d'affichage, le nom de la méthode et le numéro de ligne.
private static final int CLIENT_CODE_STACK_INDEX;
static {
// Finds out the index of "this code" in the returned stack Trace - funny but it differs in JDK 1.5 and 1.6
int i = 0;
for (StackTraceElement ste : Thread.currentThread().getStackTrace()) {
i++;
if (ste.getClassName().equals(Trace.class.getName())) {
break;
}
}
CLIENT_CODE_STACK_INDEX = i;
}
private String methodName() {
StackTraceElement ste=Thread.currentThread().getStackTrace()[CLIENT_CODE_STACK_INDEX+1];
return ste.getMethodName()+":"+ste.getLineNumber();
}
Vous ne pouvez pas garantir la cohérence du numéro de ligne avec le code, surtout s'il est compilé pour publication. De toute façon, je ne recommanderais pas d'utiliser des numéros de ligne à cette fin, il serait préférable de donner une charge utile de l'endroit où l'exception a été levée (la méthode triviale consiste à définir le message pour inclure les détails de l'appel de méthode).
Vous voudrez peut-être considérer l'enrichissement des exceptions comme une technique permettant d'améliorer la gestion des exceptions http://tutorials.jenkov.com/Java-exception-handling/exception-enrichment.html
Si cela a été compilé pour publication, ce n'est pas possible. Vous voudrez peut-être examiner quelque chose comme Log4J qui vous donnera automatiquement suffisamment d’informations pour déterminer assez précisément où le code enregistré est apparu.
tout d’abord la méthode générale (dans une classe d’utilitaire, mais dans l’ancien code Java1.4, vous devrez peut-être la réécrire pour Java1.5 et plus)
/**
* Returns the first "[class#method(line)]: " of the first class not equal to "StackTraceUtils" and aclass. <br />
* Allows to get past a certain class.
* @param aclass class to get pass in the stack trace. If null, only try to get past StackTraceUtils.
* @return "[class#method(line)]: " (never empty, because if aclass is not found, returns first class past StackTraceUtils)
*/
public static String getClassMethodLine(final Class aclass) {
final StackTraceElement st = getCallingStackTraceElement(aclass);
final String amsg = "[" + st.getClassName() + "#" + st.getMethodName() + "(" + st.getLineNumber()
+")] <" + Thread.currentThread().getName() + ">: ";
return amsg;
}
Ensuite, la méthode de l’utilitaire spécifique pour obtenir le bon stackElement:
/**
* Returns the first stack trace element of the first class not equal to "StackTraceUtils" or "LogUtils" and aClass. <br />
* Stored in array of the callstack. <br />
* Allows to get past a certain class.
* @param aclass class to get pass in the stack trace. If null, only try to get past StackTraceUtils.
* @return stackTraceElement (never null, because if aClass is not found, returns first class past StackTraceUtils)
* @throws AssertionFailedException if resulting statckTrace is null (RuntimeException)
*/
public static StackTraceElement getCallingStackTraceElement(final Class aclass) {
final Throwable t = new Throwable();
final StackTraceElement[] ste = t.getStackTrace();
int index = 1;
final int limit = ste.length;
StackTraceElement st = ste[index];
String className = st.getClassName();
boolean aclassfound = false;
if(aclass == null) {
aclassfound = true;
}
StackTraceElement resst = null;
while(index < limit) {
if(shouldExamine(className, aclass) == true) {
if(resst == null) {
resst = st;
}
if(aclassfound == true) {
final StackTraceElement ast = onClassfound(aclass, className, st);
if(ast != null) {
resst = ast;
break;
}
}
else
{
if(aclass != null && aclass.getName().equals(className) == true) {
aclassfound = true;
}
}
}
index = index + 1;
st = ste[index];
className = st.getClassName();
}
if(isNull(resst)) {
throw new AssertionFailedException(StackTraceUtils.getClassMethodLine() + " null argument:" + "stack trace should null"); //$NON-NLS-1$
}
return resst;
}
static private boolean shouldExamine(String className, Class aclass) {
final boolean res = StackTraceUtils.class.getName().equals(className) == false && (className.endsWith(LOG_UTILS
) == false || (aclass !=null && aclass.getName().endsWith(LOG_UTILS)));
return res;
}
static private StackTraceElement onClassfound(Class aclass, String className, StackTraceElement st) {
StackTraceElement resst = null;
if(aclass != null && aclass.getName().equals(className) == false)
{
resst = st;
}
if(aclass == null)
{
resst = st;
}
return resst;
}
Ils vous donnent tous les numéros de ligne de votre thread et de votre méthode actuels, ce qui fonctionne très bien si vous utilisez un catch try où vous attendez une exception. Mais si vous voulez intercepter une exception non gérée, vous utilisez le gestionnaire d'exceptions par défaut non capturé et le thread actuel renvoie le numéro de ligne de la fonction de gestionnaire, et non la méthode de classe ayant généré l'exception. Au lieu d'utiliser Thread.currentThread (), utilisez simplement le Throwable transmis par le gestionnaire d'exceptions:
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
public void uncaughtException(Thread t, Throwable e) {
if(fShowUncaughtMessage(e,t))
System.exit(1);
}
});
Dans ce qui précède, utilisez e.getStackTrace () [0] dans votre fonction de gestionnaire (fShowUncaughtMessage) pour obtenir le délinquant.
Le code ci-dessous est un code testé pour la ligne de journalisation. Aucun nom de classe ni nom de méthode à partir duquel la méthode de journalisation est appelée
public class Utils {
/*
* debug variable enables/disables all log messages to logcat
* Useful to disable prior to app store submission
*/
public static final boolean debug = true;
/*
* l method used to log passed string and returns the
* calling file as the tag, method and line number prior
* to the string's message
*/
public static void l(String s) {
if (debug) {
String[] msg = trace(Thread.currentThread().getStackTrace(), 3);
Log.i(msg[0], msg[1] + s);
} else {
return;
}
}
/*
* l (tag, string)
* used to pass logging messages as normal but can be disabled
* when debug == false
*/
public static void l(String t, String s) {
if (debug) {
Log.i(t, s);
} else {
return;
}
}
/*
* trace
* Gathers the calling file, method, and line from the stack
* returns a string array with element 0 as file name and
* element 1 as method[line]
*/
public static String[] trace(final StackTraceElement e[], final int level) {
if (e != null && e.length >= level) {
final StackTraceElement s = e[level];
if (s != null) { return new String[] {
e[level].getFileName(), e[level].getMethodName() + "[" + e[level].getLineNumber() + "]"
};}
}
return null;
}
}