How to Get the Caller Class in Java

How can I get the caller class object from a method in java?

Get the classname using the code of your linked question: How to get the caller class in Java

Then use the classname to retrieve the class, using code from here: Getting class by its name

Complete code:

String callerName = Thread.currentThread().getStackTrace()[2].getClassName();

try {
Class<?> caller = Class.forName(callerName);
// Do something with it ...
} catch (ClassNotFoundException e) {
e.printStackTrace();
}

(community answer, since only mix of existing answers).

Get the name of a calling class without the use of Exceptions

a) no need to use Exception, you can do this: Thread.currentThread().getStackTrace()

b) whatever you are trying to do, don't do it that way. That sounds awful. I guess you should be looking into logging via AOP (here's a small tutorial that looks reasonable).

How to get a caller class of a method

This is easily done with Thread.currentThread().getStackTrace().

public static void main(String[] args) {
doSomething();
}

private static void doSomething() {
System.out.println(getCallerClass());
}

private static Class<?> getCallerClass() {
final StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
String clazzName = stackTrace[3].getClassName();
try {
return Class.forName(clazzName);
} catch (ClassNotFoundException e) {
e.printStackTrace();
return null;
}
}

[3] is used because [0] is the element for Thread.currentThread(), [1] is for getCallerClass, [2] is for doSomething, and finally, [3] is main. If you put doSomething in another class, you'll see it returns the correct class.

How to get caller class' logger

Step 1: Get the caller class. To avoid duplication, see this Q&A: https://stackoverflow.com/a/45811032/2170192

Step 2: Get logger by the caller class.

How to check caller class origin in SecurityManager?

First, SecurityManager has a protected method getClassContext().

Your code would look like this:

System.setSecurityManager(new SecurityManager() {
public void checkPermission(Permission permission) {
Class<?> caller = getClassContext()[1];
ClassLoader ccl = caller.getClassLoader();
if (ccl != null || ccl != getClass().getClassLoader()) {
throw new SecurityException("You do not have permissions.");
}
}
});

Second, if you want to use a StackWalker, it is recommended that you reuse the StackWalker instance:

StackWalker walker = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE);
System.setSecurityManager(new SecurityManager() {
public void checkPermission(Permission permission) {
Class<?> caller = walker.getCallerClass();
ClassLoader ccl = caller.getClassLoader();
if (ccl != null || ccl != getClass().getClassLoader()) {
throw new SecurityException("You do not have permissions.");
}
}
});

Third, this will most likely not do what you want. Security checks are done all over the JDK, so the caller might be any amount of stack levels away, requiring you to check the entire stack (Hint: break at the second time you visit your SecurityManager in the stack).


Instead, define a policy (create a java policy file) where you grant your code all permissions and use the java.lang.SecurityManager.

If it is not possible to write your own policy file, you can also use Policy.setPolicy() to install your own implementation of java.security.Policy.

Some hints for implementing a java.security.Policy:

  • Override implies and both getPermissions methods. Seriously.
  • Catch your own ProtectionDomain of your Policy class. (private static final ProtectionDomain MY_PD = MyPolicy.class.getProtectionDomain())
  • Use a fast path if the check is for your own ProtectionDomain. Don't call other code in this case, otherwise you might end up with a StackOverflow.

Get caller class and method name

Unfortunately, there is no non-expensive method to do this. There is a Java Enhancement Proposal to add a better alternative, but this doesn't help unless you can wait until Java 9 (and it isn't guaranteed to be included anyway).

On the other hand, is this really a hotspot in your code? This should only matter if it's called in a loop, and in this case you probably can call it once and cache the result.

Is there any way to know the caller class name?

You can use Thread.currentThread().getStackTrace() to get a stack trace, then iterate through it to find which method is above yours in the stack.

For example (totally made up stack here), you might have a stack like this:

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

Starting from the bottom, you iterate up until you hit the getStackTrace() method. You then know that the calling method is two methods up from that position, i.e. MyFunction() called getStackTrace(), which means that MyFunction() will always be above getStackTrace(), and whatever called MyFunction() will be above it.

You can use the getClassName() method on the StackTraceElement class to pull out 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



Related Topics



Leave a reply



Submit