Làm thế nào chúng ta có thể in số dòng để đăng nhập java


132

Làm thế nào để in số dòng vào nhật ký. Nói khi xuất một số thông tin vào nhật ký, tôi cũng muốn in số dòng nơi đầu ra đó nằm trong mã nguồn. Như chúng ta có thể thấy trong theo dõi ngăn xếp, nó hiển thị số dòng nơi xảy ra ngoại lệ. Dấu vết ngăn xếp có sẵn trên các đối tượng ngoại lệ.

Cách khác có thể giống như thủ công bao gồm số dòng khi in vào nhật ký. Còn cách nào khác không?


4
xem câu trả lời dưới mức của Juan dưới đây cho một lớp lót ngắn và ngọt ngào! tôi vừa bỏ 15 điểm hạ gục tất cả các câu trả lời khác: v và nâng cao Juan
necromancer

Câu trả lời:


102

Từ Chsraborty Angsuman :

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

5
Điều này sẽ luôn trả về số dòng của câu lệnh return trong phương thức được gọi và không nhất thiết là số dòng của lệnh gọi phương thức.
Ron Tuffin

Không phải [2] có được khung ở trên getLineNumber () không? ([1] là getLineNumber () và [0] là getStackTrace (), có lẽ)
Simon Buchan

1
Tôi đã chơi xung quanh một chút và nếu bạn sử dụng blah.getStackTrace [3] .getLineNumber () làm phần thân phương thức, nó sẽ trả về số dòng nơi phương thức được gọi.
Ron Tuffin

12
Chỉ mục sẽ thay đổi dựa trên phiên bản JVM. Tôi tin rằng nó đã thay đổi từ 1,4 lên 1,5.
Ed Thomas

2
Xin chào @SimonAWan, Chàng trai có tên :) Tôi đã viết bài báo đó từ lâu.
Chsraborty Angsuman

74

Chúng tôi đã kết thúc bằng cách sử dụng một lớp tùy chỉnh như thế này cho công việc Android của chúng tôi:

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
Xin chào Michael, cảm ơn vì giải pháp của bạn, nó hoạt động tốt khi tôi hiển thị số dòng cho thông tin nhật ký .... cảm ơn một lần nữa. Tôi đang mong chờ các giải pháp tuyệt vời của bạn trong Android.
sathish

3
Tôi sẽ thực hiện một số nghiên cứu thêm về mã này trước khi sử dụng nó - khi tôi đăng mã, getStackTrace () [3] đã hoạt động. Nó có thể phụ thuộc vào phiên bản Android hoặc JVM hoặc một số yếu tố khác.
Michael Baltaks

3
câu trả lời này không hoạt động, nó hiển thị số dòng và tên lớp và tên hàm của lớp DebugLog không phải là dòng không có người gọi từ lớp khác
Rahul

@Rahul nên getStackTrace()[3]thay thếgetStackTrace()[2]
user5480949

@ user5480949: Sử dụng "new throwable (). getStackTrace ()" để có được một chỉ mục nhất quán cho chức năng gọi của bạn, bất kể JVM. (Thay vì Thread.cienThread (). GetStackTrace ())
Luc Bloom

36

Cách nhanh và bẩn:

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

Với một số chi tiết:

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

Điều đó sẽ tạo ra một cái gì đó như thế này:

com.example.mytest.MyClass/myMethod:103

1
System.out.println("i am here: " + new Exception().getStackTrace()[0]);cung cấp cho tôi tất cả các chi tiết tôi cần :)
necromancer

Lưu ý rằng JVM không được đảm bảo để cung cấp một stacktrace trong trường hợp này là chính xác. Tôi không tin Hotspot đảm bảo điều đó (nhưng stacktraces của nó thường chính xác).
Thorbjørn Ravn Andersen

rất sạch sẽ, lớp StackTraceEuity l = new Exception (). getStackTrace () [1]; làm việc với tôi
vuhung3990 7/215

@ ThorbjørnRavnAndersen: Sử dụng "new throwable (). GetStackTrace ()" để có được một chỉ mục nhất quán cho chức năng gọi của bạn, bất kể JVM. (Thay vì Thread.cienThread (). GetStackTrace ())
Luc Bloom

@LucBloom ngày xưa bạn không đảm bảo rằng dấu vết ngăn xếp là chính xác.
Thorbjørn Ravn Andersen

25

Tôi buộc phải trả lời bằng cách không trả lời câu hỏi của bạn. Tôi giả sử rằng bạn đang tìm kiếm số dòng chỉ để hỗ trợ gỡ lỗi. Có nhiều cách tốt hơn. Có nhiều cách hackish để có được dòng hiện tại. Tất cả những gì tôi thấy là chậm. Bạn nên sử dụng một khung ghi nhật ký như thế trong gói java.util.logging hoặc log4j . Sử dụng các gói này, bạn có thể định cấu hình thông tin đăng nhập của mình để đưa ngữ cảnh xuống tên lớp. Sau đó, mỗi thông điệp tường trình sẽ đủ độc đáo để biết nó đến từ đâu. Do đó, mã của bạn sẽ có biến 'logger' mà bạn gọi qua

logger.debug("a really descriptive message")

thay vì

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


15

Log4J cho phép bạn bao gồm số dòng như một phần của mẫu đầu ra của nó. Xem http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/PotypeLayout.html để biết chi tiết về cách thực hiện việc này (yếu tố chính trong mẫu chuyển đổi là "L"). Tuy nhiên, Javadoc bao gồm những điều sau đây:

CẢNH BÁO Tạo thông tin vị trí người gọi cực kỳ chậm. Nên tránh sử dụng trừ khi tốc độ thực thi không phải là vấn đề.


Cơ chế cơ bản đã trở nên nhanh hơn nhiều trong các phiên bản gần đây hơn của JVM, nhưng nó vẫn nên được sử dụng một cách tiết kiệm.
Thorbjørn Ravn Andersen

7

Mã được đăng bởi @ simon.buchan sẽ hoạt động ...

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

Nhưng nếu bạn gọi nó trong một phương thức, nó sẽ luôn trả về số dòng của dòng trong phương thức, thay vì sử dụng đoạn mã nội tuyến.


Tôi đoán '2' là để có được số dòng của người gọi getLineNumber ().
Simon Buchan

@ simon.buchan - chỉnh sửa câu trả lời của bạn (theo nhận xét cuối cùng của tôi). Tôi không muốn đánh cắp đại diện của bạn cho câu trả lời của bạn.
Ron Tuffin

Hoặc thay đổi 2 thành số khác. Tùy thuộc vào độ sâu của nó được lồng.
clankill3r

7

Tôi khuyên bạn nên sử dụng bộ công cụ ghi nhật ký như log4j . Ghi nhật ký có thể định cấu hình thông qua các tệp thuộc tính trong thời gian chạy và bạn có thể bật / tắt các tính năng như ghi nhật ký số dòng / tên tệp.

Nhìn vào javadoc cho PatternLayout cung cấp cho bạn danh sách đầy đủ các tùy chọn - thứ bạn đang theo là% L.


7

Tôi sử dụng phương thức nhỏ này để xuất ra dấu vết và số dòng của phương thức được gọi là phương thức đó.

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

Nhấp đúp chuột vào đầu ra để đi đến dòng mã nguồn đó!

Bạn có thể cần điều chỉnh giá trị cấp tùy thuộc vào nơi bạn đặt mã.

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

1
Điều này Utilđến từ đâu?
Hết

@benj Utils chỉ là lớp học chung mà bạn có quyền kiểm soát. Bạn có thể đặt phương thức trong bất kỳ lớp nào (lưu ý phương thức là tĩnh).
Sydwell

1
OK, tôi chỉ muốn chắc chắn. Cảm ơn vì mã tốt đẹp này.
Ngày

1

Bạn không thể đảm bảo tính nhất quán của số dòng với mã, đặc biệt nếu nó được biên dịch để phát hành. Tôi không khuyên bạn nên sử dụng số dòng cho mục đích đó, tốt hơn là nên đưa ra một trọng tải của nơi xảy ra ngoại lệ (phương pháp tầm thường là đặt thông báo để bao gồm các chi tiết của lệnh gọi phương thức).

Bạn có thể muốn xem làm giàu ngoại lệ như một kỹ thuật để cải thiện xử lý ngoại lệ http://tutorials.jenkov.com/java-exception-handling/exception-enrichment.html


0

Nếu nó được biên dịch để phát hành thì điều này là không thể. Bạn có thể muốn xem xét một cái gì đó như Log4J, nó sẽ tự động cung cấp cho bạn đủ thông tin để xác định khá chặt chẽ nơi mã đăng nhập xảy ra.


0

đầu tiên là phương thức chung (trong một lớp tiện ích, mặc dù là mã java1.4 cũ, bạn có thể phải viết lại cho java1.5 trở lên)

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

Sau đó, phương thức tiện ích cụ thể để có được stackEuity đúng:

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

Nhìn vào liên kết này . Trong phương pháp đó, bạn có thể chuyển đến mã dòng của mình, khi bạn nhấp đúp vào hàng của LogCat.

Ngoài ra, bạn có thể sử dụng mã này để lấy số dòng:

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

Tất cả đều giúp bạn có được số dòng của chủ đề và phương thức hiện tại của bạn, nó hoạt động rất tốt nếu bạn sử dụng một thử bắt trong trường hợp bạn đang mong đợi một ngoại lệ. Nhưng nếu bạn muốn bắt bất kỳ ngoại lệ nào chưa được xử lý thì bạn đang sử dụng trình xử lý ngoại lệ chưa được mặc định và luồng hiện tại sẽ trả về số dòng của hàm xử lý, chứ không phải phương thức lớp đã ném ngoại lệ. Thay vì sử dụng Thread.cienThread (), chỉ cần sử dụng throwable được truyền bởi trình xử lý ngoại lệ:

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

Trong phần trên, sử dụng e.getStackTrace () [0] trong hàm xử lý của bạn (fShowUncaughtMessage) để có được người vi phạm.


0

Mã bên dưới được kiểm tra mã để ghi nhật ký dòng không có tên lớp và tên phương thức từ đó phương thức ghi nhật ký được gọi

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

Sự stackLevelphụ thuộc vào độ sâu bạn gọi phương pháp này. Bạn có thể thử từ 0 đến một số lớn để xem sự khác biệt.

Nếu stackLevelhợp pháp, bạn sẽ nhận được chuỗi như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

Đây chính xác là tính năng tôi đã triển khai trong lib XDDLib này . (Nhưng, nó dành cho Android)

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

nhập mô tả hình ảnh ở đây

Một cú nhấp chuột vào văn bản được gạch chân để điều hướng đến nơi lệnh log

Điều đó StackTraceElementđược xác định bởi yếu tố đầu tiên bên ngoài thư viện này. Do đó, bất cứ nơi nào bên ngoài lib này sẽ quy phạm pháp luật, bao gồm lambda expression, static initialization blockvv


-1

Cách của tôi nó làm việc cho tôi

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

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.