Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get the caller class in Java [duplicate]

Tags:

java

I want to get the caller class of the method, i.e.

class foo{    bar();  } 

In the method bar, I need to get the class name foo, and I found this method:

Class clazz = sun.reflect.Reflection.getCallerClass(1); 

However, even though getCallerClass is public, when I try to call it Eclipse says:

Access restriction: The method getCallerClass() from the type Reflection is not accessible due to restriction on required library C:\Program Files\Java\jre7\lib\rt.jar

Are there any other choices?

like image 693
Foredoomed Avatar asked Jul 03 '12 08:07

Foredoomed


People also ask

How do you reference a call object in Java?

The dot ( . ) is used to access the object's attributes and methods. To call a method in Java, write the method name followed by a set of parentheses (), followed by a semicolon ( ; ).

How do I call the same method in the same class?

In this program, you have to first make a class name 'CallingMethodsInSameClass' inside which you call the main() method. This main() method is further calling the Method1() and Method2(). Now you can call this as a method definition which is performing a call to another lists of method.

What is caller method in Java?

The calling method is the method that contains the actual call. The called method is the method being called. They are different. They are also called the Caller and the Callee methods. For example int caller(){ int x=callee(); } int callee(){ return 5; }


2 Answers

You can generate a stack trace and use the informations in the StackTraceElements.

For example an utility class can return you the calling class name :

public class KDebug {     public static String getCallerClassName() {          StackTraceElement[] stElements = Thread.currentThread().getStackTrace();         for (int i=1; i<stElements.length; i++) {             StackTraceElement ste = stElements[i];             if (!ste.getClassName().equals(KDebug.class.getName()) && ste.getClassName().indexOf("java.lang.Thread")!=0) {                 return ste.getClassName();             }         }         return null;      } } 

If you call KDebug.getCallerClassName() from bar(), you'll get "foo".

Now supposing you want to know the class of the method calling bar (which is more interesting and maybe what you really wanted). You could use this method :

public static String getCallerCallerClassName() {      StackTraceElement[] stElements = Thread.currentThread().getStackTrace();     String callerClassName = null;     for (int i=1; i<stElements.length; i++) {         StackTraceElement ste = stElements[i];         if (!ste.getClassName().equals(KDebug.class.getName())&& ste.getClassName().indexOf("java.lang.Thread")!=0) {             if (callerClassName==null) {                 callerClassName = ste.getClassName();             } else if (!callerClassName.equals(ste.getClassName())) {                 return ste.getClassName();             }         }     }     return null;  } 

Is that for debugging ? If not, there may be a better solution to your problem.

like image 167
Denys Séguret Avatar answered Sep 17 '22 04:09

Denys Séguret


StackTrace

This Highly depends on what you are looking for... But this should get the class and method that called this method within this object directly.

  • index 0 = Thread
  • index 1 = this
  • index 2 = direct caller, can be self.
  • index 3 ... n = classes and methods that called each other to get to the index 2 and below.

For Class/Method/File name:

Thread.currentThread().getStackTrace()[2].getClassName(); Thread.currentThread().getStackTrace()[2].getMethodName(); Thread.currentThread().getStackTrace()[2].getFileName(); 

For Class:

Class.forName(Thread.currentThread().getStackTrace()[2].getClassName()) 

FYI: Class.forName() throws a ClassNotFoundException which is NOT runtime. Youll need try catch.

Also, if you are looking to ignore the calls within the class itself, you have to add some looping with logic to check for that particular thing.

Something like... (I have not tested this piece of code so beware)

StackTraceElement[] stes = Thread.currentThread().getStackTrace(); for(int i=2;i<stes.length;i++)   if(!stes[i].getClassName().equals(this.getClass().getName()))     return stes[i].getClassName(); 

StackWalker

StackWalker StackFrame

Note that this is not an extensive guide but an example of the possibility.

Prints the Class of each StackFrame (by grabbing the Class reference)

StackWalker.getInstance(Option.RETAIN_CLASS_REFERENCE)     .forEach(frame -> System.out.println(frame.getDeclaringClass())); 

Does the same thing but first collects the stream into a List. Just for demonstration purposes.

StackWalker.getInstance(Option.RETAIN_CLASS_REFERENCE)     .walk(stream -> stream.collect(Collectors.toList()))     .forEach(frame -> System.out.println(frame.getDeclaringClass())); 
like image 35
Atspulgs Avatar answered Sep 17 '22 04:09

Atspulgs