Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get the line number of a method?

Is it possible to get the line number of an method using reflection or other magic?
It is possible if the method is inside the current Stacktrace. Using Thread.currentThread().getStackTrace(), one can get the line number of an StackTraceElement. But what can I do if I only got the java.lang.reflect.Method Object?

I found this, for classes-> How to get source file-name/line-number from a java.lang.Class object but it's not useful for methods.

like image 500
Chriss Avatar asked Oct 11 '12 08:10

Chriss


People also ask

How to get the line number of method in Java?

The java. lang. StackTraceElement. getLineNumber() method returns the line number of the source line containing the execution point represented by this stack trace element.

How do you number a line in Java?

This class defines methods setLineNumber(int) and getLineNumber() for setting and getting the current line number respectively. By default, line numbering begins at 0. This number increments at every line terminator as the data is read, and can be changed with a call to setLineNumber(int) .


2 Answers

I wanted to do the same thing and after some research settled on javassist. You will need to add javassist (I used version 3.15.0-GA).

Given the following class determine the location of the "x" method. The method name "x" is hard coded however if you are in the same boat as me, the reflection isn't hard so I'm confident you can get a list of method names, then the following will let you get the line numbers of the methods:

public class Widget {
    void x(){System.out.println("I'm x\n");}
    //comment added to create space
    void y(){System.out.println("I'm y\n");} 
}

import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.NotFoundException;

public class App {
    public static void main(String[] args) throws NotFoundException {
        System.out.println("Get method line number with javassist\n");
        ClassPool pool = ClassPool.getDefault();
        CtClass cc = pool.get("com.quaternion.demo.Widget");
        CtMethod methodX = cc.getDeclaredMethod("x");
        int xlineNumber = methodX.getMethodInfo().getLineNumber(0);
        System.out.println("method x is on line " + xlineNumber + "\n");
    }
}

Output: method x is on line 12 which in my case is accurate I cut out some comments...

Note: As mentioned by Pete83 in the comments, this method actually returns the first line of code in the method and not the line which declares the method. This usually won't be an issue as most will probably want to establish relative position (the order in which they were declared) and use this information for your own conventions. This would come up any time you felt the need to include an ordinal value within an annotation which could be readily determined by the position within the code itself.


For quick reference Maven coordinates for javassist:
<dependency>
   <groupId>org.javassist</groupId> <!-- if a version prior to 3.13.0-GA is needed use "javassist" and not "org.javassist" -->
   <artifactId>javassist</artifactId>
   <version>3.15.0-GA</version>
</dependency>
like image 89
Quaternion Avatar answered Oct 22 '22 17:10

Quaternion


For me the answer of Quaternion pointing to Javassist is the perfect solution to this question. It works for me and you can use it also when you only get the java.lang.reflect.Method object.

This is how I did it:

Method m; // the method object
ClassPool pool = ClassPool.getDefault();
CtClass cc = pool.get(m.getDeclaringClass().getCanonicalName());
CtMethod javassistMethod = cc.getDeclaredMethod(m.getName());
int linenumber = javassistMethod.getMethodInfo().getLineNumber(0);
like image 20
Thorben Avatar answered Oct 22 '22 18:10

Thorben