it-swarm.com.de

Wie können wir Zeilennummern an das Log in Java drucken

So drucken Sie Zeilennummern in das Protokoll. Bei der Ausgabe einiger Informationen in das Protokoll möchte ich auch die Zeilennummer drucken, in der sich diese Ausgabe im Quellcode befindet. Wie in der Stack-Ablaufverfolgung zu sehen ist, wird die Zeilennummer angezeigt, in der die Ausnahme aufgetreten ist. Stack-Trace ist für das Ausnahmeobjekt verfügbar.

Eine andere Alternative könnte der manuellen Eingabe der Zeilennummer beim Drucken in das Protokoll ähneln. Gibt es einen anderen Weg?

123
Bobby Kumar

Von Angsuman Chakraborty :

/** Get the current line number.
 * @return int - Current line number.
 */
public static int getLineNumber() {
    return Thread.currentThread().getStackTrace()[2].getLineNumber();
}
90
Simon Buchan

Wir haben letztendlich eine benutzerdefinierte Klasse wie diese für unsere Android-Arbeit verwendet:

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);
  }
 }
}
70
Michael Baltaks

Schnell und schmutzig:

System.out.println("I'm in line #" + 
    new Exception().getStackTrace()[0].getLineNumber());

Mit einigen weiteren Details:

StackTraceElement l = new Exception().getStackTrace()[0];
System.out.println(
    l.getClassName()+"/"+l.getMethodName()+":"+l.getLineNumber());

Das wird etwas wie folgt ausgeben:

com.example.mytest.MyClass/myMethod:103
30
Juan

Ich bin gezwungen zu antworten, indem ich Ihre Frage nicht beantworte. Ich gehe davon aus, dass Sie nach der Zeilennummer suchen, um das Debuggen zu unterstützen. Es gibt bessere Wege. Es gibt hackische Möglichkeiten, die aktuelle Zeile abzurufen. Alles was ich gesehen habe ist langsam. Verwenden Sie besser ein Protokollierungsframework wie das im Java.util.logging-Paket oder log4j . Mit diesen Paketen können Sie Ihre Protokollierungsinformationen so konfigurieren, dass sie den Kontext bis zum Klassennamen enthalten. Dann wäre jede Protokollnachricht eindeutig genug, um zu wissen, woher sie kam. Infolgedessen verfügt Ihr Code über eine 'Logger'-Variable, die Sie über aufrufen

logger.debug("a really descriptive message")

anstatt

System.out.println("a really descriptive message")

24
James A Wilson

Mit Log4J können Sie die Zeilennummer als Teil des Ausgabemusters hinzufügen. Unter http://logging.Apache.org/log4j/1.2/apidocs/org/Apache/log4j/PatternLayout.html finden Sie Einzelheiten zur Vorgehensweise (das Schlüsselelement im Konvertierungsmuster ist "L"). . Das Javadoc enthält jedoch Folgendes:

WARNUNG Anruferstandort generieren Informationen sind extrem langsam. Es ist Die Verwendung sollte vermieden werden, es sei denn, die Ausführung Geschwindigkeit ist kein Problem.

14
Jim Kiley

Ich benutze diese kleine Methode, die die Trace- und Zeilennummer der Methode ausgibt, die sie aufgerufen hat. 

 Log.d(TAG, "Where did i put this debug code again?   " + Utils.lineOut());

Doppelklicken Sie auf die Ausgabe, um zu dieser Quellcodezeile zu gelangen!

Möglicherweise müssen Sie den Pegelwert anpassen, je nachdem, wo Sie Ihren Code eingeben.

public static String lineOut() {
    int level = 3;
    StackTraceElement[] traces;
    traces = Thread.currentThread().getStackTrace();
    return (" at "  + traces[level] + " " );
}
7
Sydwell

Der von @ simon.buchan veröffentlichte Code wird funktionieren ...

Thread.currentThread().getStackTrace()[2].getLineNumber()

Wenn Sie es jedoch in einer Methode aufrufen, wird immer die Zeilennummer der Zeile in der Methode zurückgegeben. Verwenden Sie also den Code-Snippet inline. 

7
Ron Tuffin

Ich würde empfehlen, ein Logging-Toolkit wie log4j zu verwenden. Die Protokollierung ist zur Laufzeit über Eigenschaftendateien konfigurierbar. Sie können Funktionen wie z. B. Protokollierung von Zeilennummern/Dateinamen aktivieren/deaktivieren.

Wenn Sie sich den Javadoc für das PatternLayout anschauen, erhalten Sie die vollständige Liste der Optionen - Sie suchen nach% L.

6
user7094

Die stackLevel hängt von der Tiefe ab, in der Sie diese Methode aufrufen. Sie können von 0 bis zu einer großen Zahl versuchen, um den Unterschied festzustellen.

Wenn stackLevel legal ist, erhalten Sie Zeichenfolgen wie 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);
}
0
Loyea

Dies ist genau die Funktion, die ich in dieser Bibliothek implementiert habe XDDLib . (Aber es ist für Android)

Lg.d("int array:", intArrayOf(1, 2, 3), "int list:", listOf(4, 5, 6))

enter image description here

Ein Klick auf den unterstrichenen Text , um zur Position des Protokollbefehls zu navigieren

Das StackTraceElement wird durch das erste Element außerhalb dieser Bibliothek bestimmt. Somit ist jeder Ort außerhalb dieser Bibliothek legal, einschließlich lambda expression, static initialization block usw.

0
Owen Chen

Schau dir diesen Link an. In dieser Methode können Sie zu Ihrem Zeilencode springen, indem Sie auf die Zeile von LogCat doppelklicken.

Sie können diesen Code auch verwenden, um die Zeilennummer zu erhalten:

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;
}
0
Bobs

Hier ist der Logger, den wir verwenden. 

es umschließt Android Logger und zeigt Klassennamen, Methodennamen und Zeilennummer an.

http://www.hautelooktech.com/2011/08/15/Android-logging/

0
jimmy.hautelook
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();
}
0
Raymond

Sie können die Konsistenz der Zeilennummer mit Code nicht garantieren, insbesondere wenn sie für die Veröffentlichung kompiliert wird. Ich würde es ohnehin nicht empfehlen, Zeilennummern zu verwenden, es wäre besser, eine Payload des Ortes anzugeben, an dem die Ausnahme ausgelöst wurde (die triviale Methode besteht darin, die Nachricht so zu definieren, dass sie die Details des Methodenaufrufs enthält).

Sie können die Anreicherung von Ausnahmen als eine Methode zur Verbesserung der Ausnahmebehandlung betrachten http://tutorials.jenkov.com/Java-exception-handling/exception-enrichment.html

0
UberAlex

Wenn es für die Veröffentlichung kompiliert wurde, ist dies nicht möglich. Vielleicht möchten Sie sich etwas wie Log4J ansehen, das Ihnen automatisch genug Informationen liefert, um genau zu bestimmen, wo der protokollierte Code aufgetreten ist.

0
GBa

zuerst die allgemeine Methode (in einer Dienstprogrammklasse, in einfachem alten Java1.4-Code müssen Sie sie jedoch möglicherweise für Java1.5 und mehr neu schreiben.)

/**
 * 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;
}

Dann die spezifische Utility-Methode, um das richtige stackElement zu erhalten:

/**
   * 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;
  }
0
VonC

All dies liefert Ihnen die Zeilennummern Ihres aktuellen Threads und Ihrer Methode, die sich hervorragend eignen, wenn Sie einen try-Catch verwenden, bei dem Sie eine Ausnahme erwarten. Wenn Sie jedoch eine nicht behandelte Ausnahme abfangen möchten, verwenden Sie den Standard-Handler für nicht erfasste Ausnahmen, und der aktuelle Thread gibt die Zeilennummer der Handlerfunktion zurück, nicht die Klassenmethode, die die Ausnahme ausgelöst hat. Verwenden Sie anstelle von Thread.currentThread () einfach das Throwable, das vom Exception-Handler übergeben wird:

Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
            public void uncaughtException(Thread t, Throwable e) {              
                if(fShowUncaughtMessage(e,t))               
                    System.exit(1);
            }
        });

Verwenden Sie e.getStackTrace () [0] in Ihrer Handler-Funktion (fShowUncaughtMessage), um den Täter zu erhalten.

0
Mark

Unter dem Code wird Code für die Protokollierung getestet. Zeile, Klassenname und Methodenname, aus der die Protokollierungsmethode aufgerufen wird.

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;
}
}
0
Rahul