Dynamically get the current line number

Starting from JDK9 you can use the StackWalker. This gave me around a 50% of speed increase over using getStackTrace().

int get_line_number() {
    return StackWalker.getInstance(StackWalker.Option.SHOW_HIDDEN_FRAMES).walk(
      (s) -> s.skip(1).findFirst()).get().getLineNumber();
}

My stream could be done better but I have no experience with it, and I really don't like streams in general, so feel free to edit my post to improve this part.


I was able to use the Thread.currentThread().getStackTrace() method to create a set of functions that work together to produce the line number of the code that called the first method, like so:

/** @return The line number of the code that ran this method
 * @author Brian_Entei */
public static int getLineNumber() {
    return ___8drrd3148796d_Xaf();
}

/** This methods name is ridiculous on purpose to prevent any other method
 * names in the stack trace from potentially matching this one.
 * 
 * @return The line number of the code that called the method that called
 *         this method(Should only be called by getLineNumber()).
 * @author Brian_Entei */
private static int ___8drrd3148796d_Xaf() {
    boolean thisOne = false;
    int thisOneCountDown = 1;
    StackTraceElement[] elements = Thread.currentThread().getStackTrace();
    for(StackTraceElement element : elements) {
        String methodName = element.getMethodName();
        int lineNum = element.getLineNumber();
        if(thisOne && (thisOneCountDown == 0)) {
            return lineNum;
        } else if(thisOne) {
            thisOneCountDown--;
        }
        if(methodName.equals("___8drrd3148796d_Xaf")) {
            thisOne = true;
        }
    }
    return -1;
}

Hope this helps! I put these in a utility class so that they are out of the way, but still easily accessible. The second method is private to prevent any other method other than the first method from calling it so that it always works correctly.


You can create a Throwable and use its StackTraceElements:

  System.err.println(new Throwable().getStackTrace()[0].getLineNumber());

As @Joachim said, you can also use Thread.getStackTrace(), e.g. like

  System.err.println(Thread.currentThread().getStackTrace()[1].getLineNumber());

Be aware that the second approach returns a somewhat different array - you need to use the array element with index 1 to get the current line number, since it includes the call to getStackTrace() itself as the first element.

Also note the comments about Logging and performance from @Joachim's answer.


First of all: If anything, then the logging pattern (or layouter, or whatever your logging framework calls that part) should do this. The logger call in your code should only write the actual business information. Information about the where should be added by the logger.

Next: getting that kind of operation is expensive (in terms of time), because Java is not optimized for this. At runtime, the JVM need to inspect its state, load/parse debug information and find the line number corresponding to a given instruction. That's why this kind of information is usually just given when an exception occurs (in which case we already have a problem and know that the time spent will usually be worth it).

And last but not least: if for some reason you need that information on your own, you can use Thread.getStackTrace() and inspect the second StackTraceElement on it.