자바에서 로그에 줄 번호를 인쇄하는 방법


133

줄 번호를 로그에 인쇄하는 방법 로그에 정보를 출력 할 때 해당 출력이 소스 코드에있는 줄 번호를 인쇄하고 싶습니다. 스택 추적에서 볼 수 있듯이 예외가 발생한 행 번호가 표시됩니다. 스택 추적은 예외 개체에서 사용할 수 있습니다.

다른 대안은 로그에 인쇄 할 때 줄 번호를 수동으로 포함하는 것과 같습니다. 다른 방법이 있습니까?


4
짧고 달콤한 원 라이너에 대해서는 아래 @Juan의 저평가 답변을 참조하십시오! 난 그냥 15 점 포기 다른 모든 답변을 downvoting : v와 upanting Juan 's
necromancer

답변:


102

에서 Angsuman 차크라보티 :

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

5
이것은 항상 호출 된 메소드에서 리턴 명령문의 행 번호를 리턴하며 반드시 메소드 호출의 행 번호를 리턴하지는 않습니다.
Ron Tuffin

[2]가 getLineNumber () 위의 프레임을 가져 오지 않습니까? ([1] getLineNumber () 및 인 [0] 인 getStackTrace ()에 (), 아마)
시몬 버컨

1
나는 약간 놀았고 blah.getStackTrace [3] .getLineNumber ()를 메소드 본문으로 사용하면 메소드가 호출 된 행 번호를 반환합니다.
Ron Tuffin

12
JVM 버전에 따라 색인이 변경됩니다. 1.4에서 1.5로 바뀌 었다고 생각합니다.
Ed Thomas

2
안녕하세요 @SimonBuchan, 그 남자의 이름이 있습니다 :) 나는 그 기사를 오래 전부터 썼습니다.
Angsuman Chakraborty

74

우리는 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);
  }
 }
}

1
안녕 마이클, 솔루션 주셔서 감사합니다, 로그 정보 .... 다시 감사합니다 줄 번호를 표시하는 데 잘 작동합니다. 안드로이드에서 훌륭한 솔루션을 기대하고 있습니다.
sathish

3
코드를 게시하기 전에 getStackTrace () [3]가 작동했습니다. Android 또는 JVM 버전 또는 기타 요인에 따라 달라질 수 있습니다.
Michael Baltaks

3
이 답변은 쇼 더 줄 작동하지하지 않고 클래스 이름이 아닌 라인 다른 클래스에서 발신자의 DebugLog 클래스의 함수 이름
라훌

@Rahul getStackTrace()[3]대신에getStackTrace()[2]
user5480949

@ user5480949 : "new Throwable (). getStackTrace ()"를 사용하여 JVM에 관계없이 호출 함수에 대한 일관된 색인을 얻으십시오. (Thread.currentThread (). getStackTrace () 대신)
Luc Bloom

36

빠르고 더러운 방법 :

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

자세한 내용은 다음과 같습니다.

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

다음과 같이 출력됩니다 :

com.example.mytest.MyClass/myMethod:103

1
System.out.println("i am here: " + new Exception().getStackTrace()[0]);나는 :) 필요는 나에게 모든 세부 정보를 제공합니다
네크로맨서

JVM이 올바른 위치에 스택 추적을 제공한다고 보장하지는 않습니다. 나는 Hotspot이 그 어느 것도 보증한다고 생각하지 않습니다 (그러나 스택 추적은 일반적으로 정확합니다).
Thorbjørn Ravn Andersen

매우 깨끗한 클래스 StackTraceElement l = new Exception (). getStackTrace () [1]; 나와 함께 일
vuhung3990

@ ThorbjørnRavnAndersen : "new Throwable (). getStackTrace ()"를 사용하여 JVM에 관계없이 호출 함수에 대한 일관된 색인을 얻으십시오. (Thread.currentThread (). getStackTrace () 대신)
Luc Bloom

옛날에는 @LucBloom 스택 추적이 정확하다는 것을 보장하지 못했습니다.
Thorbjørn Ravn Andersen

25

나는 당신의 질문에 대답하지 않으면 서 대답해야합니다. 디버깅을 지원하기 위해 줄 번호를 찾고 있다고 가정합니다. 더 좋은 방법이 있습니다. 현재 줄을 얻는 방법이 있습니다. 내가 본 것은 느리다. java.util.logging package 또는 log4j 와 같은 로깅 프레임 워크를 사용하는 것이 좋습니다 . 이 패키지를 사용하면 클래스 이름에 대한 컨텍스트를 포함하도록 로깅 정보를 구성 할 수 있습니다. 그런 다음 각 로그 메시지는 그 출처를 알 수있을만큼 고유합니다. 결과적으로 코드에는 '로거'변수가 있습니다.

logger.debug("a really descriptive message")

대신에

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


15

Log4J를 사용하면 라인 번호를 출력 패턴의 일부로 포함 할 수 있습니다. 이 작업을 수행하는 방법에 대한 자세한 내용 은 http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/PatternLayout.html 을 참조 하십시오 (변환 패턴의 핵심 요소는 "L"). 그러나 Javadoc에는 다음이 포함됩니다.

경고 발신자 위치 정보 생성이 매우 느립니다. 실행 속도가 문제가 아닌 한 사용을 피해야합니다.


최신 버전의 JVM에서는 기본 메커니즘이 훨씬 빨라졌지만 여전히 조금만 사용해야합니다.
Thorbjørn Ravn Andersen

7

@ simon.buchan이 게시 한 코드는 작동합니다 ...

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

그러나 메소드에서 호출하면 항상 메소드의 행 번호를 반환하므로 코드 스 니펫을 인라인으로 사용하십시오.


'2'가 getLineNumber () 호출자의 줄 번호를 얻는 것 같았습니다.
Simon Buchan

@ simon.buchan-마지막 의견에 따라 답변을 편집하십시오. 귀하의 답변에 대한 귀하의 담당자를 훔치고 싶지 않습니다.
Ron Tuffin

또는 2를 다른 숫자로 변경하십시오. 얼마나 깊이 중첩되어 있는지에 따라.
clankill3r

7

log4j 와 같은 로깅 툴킷을 사용하는 것이 좋습니다 . 런타임시 속성 파일을 통해 로깅을 구성 할 수 있으며 줄 번호 / 파일 이름 로깅과 같은 기능을 설정 / 해제 할 수 있습니다.

PatternLayout 에 대한 javadoc을 살펴보면 옵션의 전체 목록을 볼 수 있습니다. 다음은 % L입니다.


7

나는이 작은 메소드를 사용하여 호출 한 메소드의 추적 번호와 라인 번호를 출력합니다.

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

해당 소스 코드 행으로 이동하려면 출력을 두 번 클릭하십시오!

코드를 어디에 두 었는지에 따라 레벨 값을 조정해야 할 수도 있습니다.

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

1
어디 Util에서 왔습니까?
Benj

@benj Utils는 제어 할 수있는 일반적인 클래스입니다. 모든 클래스에 메소드를 넣을 수 있습니다 (메소드는 정적입니다).
Sydwell

1
좋아, 나는 단지 확신하고 싶었다. 이 멋진 코드에 감사드립니다.
Benj

1

특히 릴리스 용으로 컴파일 된 경우 코드와 줄 번호 일관성을 보장 할 수 없습니다. 어쨌든 그 목적으로 줄 번호를 사용하지 않는 것이 좋습니다. 예외가 발생한 장소의 페이로드를 제공하는 것이 좋습니다 (메소드 메소드는 메시지를 메소드 호출의 세부 사항을 포함하도록 설정하는 것이 좋습니다).

예외 처리 향상을위한 기술로 예외 강화를보고 싶을 수도 있습니다. http://tutorials.jenkov.com/java-exception-handling/exception-enrichment.html


0

릴리스 용으로 컴파일 된 경우 불가능합니다. Log4J와 같은 것을 살펴보고 로그 된 코드가 발생한 위치를 정확하게 결정할 수있는 충분한 정보를 자동으로 제공 할 수 있습니다.


0

먼저 일반적인 방법 (유틸리티 클래스, 일반 오래된 java1.4 코드에서는 java1.5 이상에서 다시 작성해야 할 수도 있음)

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

그런 다음 특정 유틸리티 메소드가 올바른 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;
  }


0

이 링크를 . 이 방법으로 LogCat 행을 두 번 클릭하면 라인 코드로 이동할 수 있습니다.

또한이 코드를 사용하여 줄 번호를 얻을 수 있습니다.

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

이것들은 모두 현재 스레드의 스레드 번호와 메소드를 얻습니다. 예외를 예상하는 곳에 try catch를 사용하면 효과적입니다. 그러나 처리되지 않은 예외를 잡으려면 기본 포착되지 않은 예외 핸들러를 사용하고 있으며 현재 스레드는 예외를 발생시킨 클래스 메소드가 아니라 핸들러 함수의 행 번호를 리턴합니다. Thread.currentThread ()를 사용하는 대신 예외 핸들러가 전달한 Throwable을 사용하십시오.

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

위의 처리기 함수 (fShowUncaughtMessage)에서 e.getStackTrace () [0]을 사용하여 가해자를 확보하십시오.


0

아래 코드는 로깅 라인에 대한 테스트 코드이며 로깅 방법이 호출되는 클래스 이름과 메소드 이름이 없습니다.

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

stackLevel이 메서드를 호출 깊이에 따라 달라집니다. 0에서 큰 수까지 시도하여 어떤 차이를 볼 수 있습니다.

stackLevel합법적 이라면 다음 과 같은 문자열을 얻습니다.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

이것이 바로이 lib XDDLib 에서 구현 한 기능 입니다. (하지만 안드로이드 용입니다)

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

여기에 이미지 설명을 입력하십시오

밑줄표시된 텍스트 를 한 번 클릭 하면 log 명령이있는 위치로 이동합니다

이는 StackTraceElement이 라이브러리 외부의 첫 번째 요소에 의해 결정됩니다. 따라서,이 lib 디렉토리 외부 어느 곳이 될 것입니다 법률, 포함 lambda expression, static initialization block


-1

그것은 나를 위해 작동하는 방식

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

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.