Satır numaralarını java'daki günlüğe nasıl yazdırabiliriz


133

Satır numaraları günlüğe nasıl yazdırılır. Günlüğe bazı bilgiler çıkarırken, bu çıktının kaynak kodda olduğu satır numarasını da yazdırmak istiyorum. Yığın izlemede görebileceğimiz gibi, istisnanın meydana geldiği satır numarasını görüntüler. İstisna nesnesinde yığın izleme mevcuttur.

Diğer alternatif, günlüğe yazdırırken satır numarasını manuel olarak eklemek gibi olabilir. Başka bir yolu var mı?


4
Kısa ve tatlı bir tek satırlık için @ Juan'ın takdir edilmeyen aşağıdaki cevabına bakın! diğer tüm cevapları olumsuz oylayarak 15 puanlık temsilciden vazgeçtim: v ve Juan'ınkine olumlu oy veriyorum
necromancer

Yanıtlar:


102

Gönderen Angsuman Chakraborty'a :

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

5
Bu, çağrılan yöntemde her zaman return ifadesinin satır numarasını döndürür ve mutlaka yöntem çağrısının satır numarasını değil.
Ron Tuffin

[2], getLineNumber () üzerindeki çerçeveyi almıyor mu? ([1] muhtemelen getLineNumber () ve [0] getStackTrace () olmak üzere)
Simon Buchan

1
Biraz oynadım ve yöntem gövdesi olarak blah.getStackTrace [3] .getLineNumber () kullanırsanız, yöntemin çağrıldığı yerin satır numarasını döndürür.
Ron Tuffin

12
Dizin, JVM sürümüne göre değişecektir. 1.4'ten 1.5'e değiştiğine inanıyorum.
Ed Thomas

2
Hey @SimonBuchan, Adamın bir adı var :) O makaleyi uzun süre önce yazdım.
Angsuman Chakraborty

74

Android çalışmamız için buna benzer özel bir sınıf kullandık:

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);
  }
 }
}

1
Merhaba Michael, çözümünüz için teşekkürler, günlük bilgileri için satır numaralarını görüntülemem gayet iyi çalışıyor .... tekrar teşekkürler. Android'deki harika çözümlerinizi dört gözle bekliyorum.
sathish

3
Kullanmadan önce bu kodu biraz daha araştırırdım - kodu gönderdiğimde getStackTrace () [3] çalıştı. Android veya JVM sürümüne veya başka bir faktöre bağlı olabilir.
Michael Baltaks

3
bu cevap işe yaramıyor DebugLog sınıfının satır numarasını ve sınıf adını ve işlev adını, diğer sınıftan arayanın satır numarasını değil
Rahul

@Rahul getStackTrace()[3]yerinegetStackTrace()[2]
user5480949

@ user5480949: JVM'den bağımsız olarak, çağrı işleviniz için tutarlı bir dizin elde etmek için "new Throwable (). getStackTrace ()" kullanın. (Thread.currentThread (). GetStackTrace () yerine)
Luc Bloom

36

Hızlı ve kirli yol:

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

Biraz daha ayrıntıyla:

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

Bu, şuna benzer bir sonuç verecektir:

com.example.mytest.MyClass/myMethod:103

1
System.out.println("i am here: " + new Exception().getStackTrace()[0]);bana ihtiyacım olan tüm ayrıntıları veriyor :)
necromancer

JVM'nin bunun doğru olduğu durumlarda bir yığın izleme vermesinin garanti edilmediğini unutmayın. Hotspot'un bu garantiyi de verdiğine inanmıyorum (ancak yığın izleri normalde doğrudur).
Thorbjørn Ravn Andersen

çok temiz, sınıf StackTraceElement l = yeni Exception (). getStackTrace () [1]; benimle
çalış

@ ThorbjørnRavnAndersen: JVM'den bağımsız olarak arama işleviniz için tutarlı bir dizin elde etmek için "new Throwable (). GetStackTrace ()" kullanın. (Thread.currentThread (). GetStackTrace () yerine)
Luc Bloom

@LucBloom Eski günlerde bir yığın izlemenin doğru olduğu garanti edilmiyordu.
Thorbjørn Ravn Andersen

25

Sorunuza cevap vermeyerek cevap vermeye mecburum. Satır numarasını yalnızca hata ayıklamayı desteklemek için aradığınızı varsayıyorum. Daha iyi yollar var. Mevcut satırı almanın hileli yolları var. Tüm gördüğüm yavaş. Java.util.logging paketi veya log4j'deki gibi bir günlük çerçevesini kullanmanız daha iyidir . Bu paketleri kullanarak günlük bilgilerinizi sınıf adına bağlam dahil edecek şekilde yapılandırabilirsiniz. Daha sonra her günlük mesajı, nereden geldiğini bilecek kadar benzersiz olacaktır. Sonuç olarak, kodunuz aracılığıyla çağırdığınız bir 'günlükçü' değişkeni olacaktır.

logger.debug("a really descriptive message")

onun yerine

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


15

Log4J, satır numarasını çıktı modelinin bir parçası olarak eklemenize izin verir. Bunun nasıl yapılacağına ilişkin ayrıntılar için http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/PatternLayout.html adresine bakın (dönüşüm modelindeki anahtar öğe "L" dir). Bununla birlikte, Javadoc şunları içerir:

UYARI Arayan konum bilgilerinin oluşturulması son derece yavaştır. Yürütme hızı bir sorun olmadığı sürece kullanımından kaçınılmalıdır.


Altta yatan mekanizma, JVM'nin daha yeni sürümlerinde çok daha hızlı hale geldi, ancak yine de idareli kullanılmalıdır.
Thorbjørn Ravn Andersen

7

@ Simon.buchan tarafından gönderilen kod çalışacaktır ...

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

Ancak, onu bir yöntemde çağırırsanız, her zaman yöntemdeki satırın satır numarasını döndürür, bu nedenle kod parçacığını satır içi olarak kullanın.


'2'nin getLineNumber () arayanının satır numarasını almak olduğunu tahmin ettim.
Simon Buchan

@ simon.buchan - cevabınızı düzenleyin (son yorumuma göre). Cevabınız için itibarınızı çalmak istemiyorum.
Ron Tuffin

Veya 2'yi başka bir sayı ile değiştirin. Ne kadar derin iç içe olduğuna bağlı.
clankill3r

7

Log4j gibi bir günlük araç seti kullanmanızı tavsiye ederim . Günlük kaydı, çalışma zamanında özellikler dosyaları aracılığıyla yapılandırılabilir ve satır numarası / dosya adı günlüğü gibi özellikleri açıp kapatabilirsiniz.

PatternLayout için javadoc'a bakmak size seçeneklerin tam listesini verir - peşinde olduğunuz şey% L'dir.


7

Onu çağıran yöntemin izini ve satır numarasını çıkaran bu küçük yöntemi kullanıyorum.

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

Bu kaynak kod satırına gitmek için çıktıya çift tıklayın!

Kodunuzu nereye koyduğunuza bağlı olarak seviye değerini ayarlamanız gerekebilir.

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

1
Bu Utilnereden geliyor?
Benj

@benj Utils, üzerinde kontrol sahibi olduğunuz genel bir sınıftır. Yöntemi herhangi bir sınıfa koyabilirsiniz (yöntemin statik olduğunu unutmayın).
Sydwell

1
Tamam, sadece emin olmak istedim. Bu güzel kod için teşekkürler.
Benj

1

Satır numarası tutarlılığını, özellikle yayınlanmak üzere derlenmişse, kodla garanti edemezsiniz. Yine de bu amaç için satır numaralarını kullanmanızı tavsiye etmem, istisnanın ortaya çıktığı yerin bir yükünü vermek daha iyi olacaktır (önemsiz yöntem, mesajı yöntem çağrısının ayrıntılarını içerecek şekilde ayarlamaktır).

İstisna işlemeyi iyileştirmek için bir teknik olarak istisna zenginleştirmeye bakmak isteyebilirsiniz http://tutorials.jenkov.com/java-exception-handling/exception-enrichment.html


0

Yayınlanmak üzere derlenmişse bu mümkün değildir. Günlüğe kaydedilen kodun nerede oluştuğunu oldukça yakından belirlemek için size otomatik olarak yeterli bilgi verecek olan Log4J gibi bir şeye bakmak isteyebilirsiniz.


0

önce genel yöntem (bir yardımcı program sınıfında, düz eski java1.4 kodunda, yine de java1.5 ve daha fazlası için yeniden yazmanız gerekebilir)

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

Ardından, doğru yığını elde etmek için belirli bir yardımcı program yöntemi:

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

Bak bu link . Bu yöntemde LogCat'ın satırına çift tıkladığınızda satır kodunuza atlayabilirsiniz.

Ayrıca satır numarasını almak için bu kodu kullanabilirsiniz:

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
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

Bunların hepsi size mevcut iş parçacığınızın satır numaralarını ve bir istisna beklediğiniz yerde bir try catch kullanırsanız harika çalışan yöntemi verir. Ancak, herhangi bir işlenmemiş istisnayı yakalamak istiyorsanız, varsayılan yakalanmamış istisna işleyicisini kullanıyorsunuzdur ve mevcut iş parçacığı, istisnayı atan sınıf yöntemini değil, işleyici işlevinin satır numarasını döndürür. Thread.currentThread () kullanmak yerine istisna işleyicisi tarafından iletilen Throwable'ı kullanın:

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

Yukarıda, suçluyu bulmak için işleyici işlevinizde (fShowUncaughtMessage) e.getStackTrace () [0] kullanın.


0

Aşağıdaki kod, günlük kaydı için test edilen kod, sınıf adı ve yöntem adı olmadan günlük yönteminin çağrıldığı yerden

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

stackLevelBu yöntemi çağırmak derinliğine bağlıdır. Aradaki farkı görmek için 0'dan büyük bir sayıya kadar deneyebilirsiniz.

Eğer stackLevelyasal ise, şöyle bir ip alacaksınızjava.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

Bu tam da bu lib XDDLib'de uyguladığım özellik . (Ama bu android için)

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

görüntü açıklamasını buraya girin

Günlük komutunun olduğu yere gitmek için altı çizili metne bir tıklama

Bu StackTraceElement, bu kitaplığın dışındaki ilk öğe tarafından belirlenir. Böylece, bu lib dışında herhangi bir yere olacak hukuki dahil lambda expression, static initialization blockvb


-1

Benim yolum benim için çalışıyor

String str = "select os.name from os where os.idos="+nameid;  try {
        PreparedStatement stmt = conn.prepareStatement(str);
        ResultSet rs = stmt.executeQuery();
        if (rs.next()) {
            a = rs.getString("os.n1ame");//<<<----Here is the ERROR          
        }
        stmt.close();
  } catch (SQLException e) {
        System.out.println("error line : " + e.getStackTrace()[2].getLineNumber());            
        return a;
  }

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.