Is there any way to find out the class name of the caller?

Let's say I have a classA.methodA() method and its call to classB.methodB() . Now, inside classB.methodB() , is there a way to find out if classA is classA (without passing any explicit information). I know this information exists in the Java Runtime. My question is how to get the callee method class name?

to make it more obvious

 ClassA{ methodA(){ ClassB b = new ClassB(); b.methodB(); } } ClassB{ methodB(){ // Code to find that its being called by ClassA } } 
+4
source share
6 answers

You can use Thread.currentThread().getStackTrace() to get the stack trace and then Thread.currentThread().getStackTrace() over it to find which method is higher than yours on the stack.

For example (a fully created stack here), you might have a stack like this:

 main() |- Foo() |- Bar() |- MyFunction() |- getStackTrace() |- captureJavaThreadStack(...) 

Starting from the bottom, you repeat until you click on the getStackTrace() method. Then you know that the calling method is two methods from this position, that is, MyFunction() is called getStackTrace() , which means that MyFunction() will always be higher than getStackTrace() , and everything called MyFunction() will be above him.

You can use the getClassName() method in the StackTraceElement class to pull the class name from the selected stack trace element.

Docs:

http://docs.oracle.com/javase/6/docs/api/java/lang/Thread.html#getStackTrace%28%29

http://docs.oracle.com/javase/6/docs/api/java/lang/StackTraceElement.html

+8
source

By running Java 5.0, you can use Thread.currentThread().getStackTrace() to get the current stack trace.

To get the class (and method) of the current call to the current method:

 StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace(); int i = 1; while (MyClass.class.getName().equals(stackTraceElements[i].getClassName())) { i++; } int lineNumber = stackTraceElements[i].getLineNumber(); String className = stackTraceElements[i].getClassName(); String methodName = stackTraceElements[i].getMethodName(); 

Note! There are some warnings in javadocs regarding this method:

Some virtual machines may, in some circumstances, omit one or more stack frames from a stack trace. In extreme cases, a virtual machine that does not have stack trace information related to this thread is allowed to return a zero-length array from this method.

I have no problem with this piece of code on the Sun (Oracle) JVM JVM and Mac OS X JVM. Please test your code carefully to make sure that it works as you expect, especially if you use any other JVM.

+3
source

Only by checking the call stack, which is not directly supported, but you can get an almost reliable answer by looking at the stack trace (just throw a RuntimeException) or ThreadDump (for Java 6).

If you want your code to act differently, based on who named it, you are most definitely heading in the wrong direction. Skip the required information or use subclasses to provide different behaviors.

+3
source

You can use stack trace for this. Inside the called method do the following

 Throwable t = new Throwable(); StackTraceElement[] stackTraceElements = t.getStackTrace(); String calleeMethod = stackTraceElements [0].getMethodName(); String callerMethodName = stackTraceElements [1].getMethodName(); String callerClassName = stackTraceElements [1].getClassName(); System.out.println("Caller :" + callerClassName + "." + callerMethodName); 
+2
source

Not a very reliable way is to browse

 Thread.currentThread().getStackTrace() 

This is not reliable, because there are different reasons why the called is not what you expect, for example. tools, reflection utilities, etc. But maybe this is good enough for your use case?

+1
source

Warning (potentially) Access Point is not a public API only

Try sun.reflect.Reflection.getCallerClass (int numFramesToSkip) ; note that this API has been deprecated .

Lately, I used this to do some ASM magic mana, to rewrite the log4j call in a third-party library so that we can fix its dumb log and make it correctly log4j categories. No, I will not mention that the third party as they are a company that is very touching regarding reverse engineering.

Notes :

  • This is not a stack frame, its reference to the class that made the call from this frame
  • This method will not give line numbers and other similar things (the JVM should "de-optimize" from the jit code and restore debugging stanzas for it, one of the reasons why stacktraces are slow)
  • This does not create stacktrace
  • In hotspot, jit actively implements this code, making it super fast (look in globals.hpp for the switch and elsewhere in the code for proof)

Now I can hear the mob screaming about a non-public example API

0
source

Source: https://habr.com/ru/post/1384096/


All Articles