Wednesday, May 14, 2008

Who am I?

If you want to check what is the current method name in Java you have two ugly possibilities to do it:

package com.bielu;

public class MethodName {

public String methodOne() {
return new Exception().getStackTrace()[0].toString();
}

public String methodTwo() {
return Thread.currentThread().getStackTrace()[2].toString();
}

public static void main(String[] args) {
MethodName name = new MethodName();

long start = System.currentTimeMillis();
for (int i = 0; i < 100000; i++) {
name.methodOne();
}
System.out.printf("First method - new Exception() - in %d millis\n",
System.currentTimeMillis() - start);

start = System.currentTimeMillis();
for (int i = 0; i < 100000; i++) {
name.methodTwo();
}

System.out.printf("Second method - Thread.currentThread() - in %d millis\n",
System.currentTimeMillis() - start);
}
}

Results from my machine:

First method - new Exception() - in 8141 millis
Second method - Thread.currentThread() - in 80561 millis


As you can see the second method is ten times slower.

In any case I do not recommend using either of the shown techniques in the production code. You should consider using AspectJ in a pure form (don't like it) or Spring Framework AOP capabilities (most preferable way).

Anyway - why should you want to know where you are? :-)

6 comments:

Kieron Wilkinson said...

Arguably, a more "correct" way of doing it would be the following:


public static Class getContext() {
return = new ContextAccessor().getCaller();
}

private static class ContextAccessor extends SecurityManager {
private Class<?> getCaller() {
return getClassContext()[3];
}
}

Przemysław Bielicki said...

You're absolutely right - your code is very arguable :)

First of all I think you wanted to write:

return getClassContext()[4];

and second of all this code shows who called you not where you are at this particular moment - and thus your code does something completely different from what I wanted to achieve ;)

More so - it doesn't show what method called you but what class.

Please copy-paste the code from my post and check what it does. It shows the METHOD name not the CLASS name - I'm not interested in a class name.

Cheers!

Kieron Wilkinson said...

Good point. Seems I unjustifiably linked what you were trying to do with the almost-entirely-different-but-not-quite-enough logging helper I wrote a while back. Whoops.

Przemysław Bielicki said...

happens ;)

Anonymous said...

Did you mean: return new Exception().getStackTrace()[1].toString();


0 returns your helper method. 1 return method that uses helper method.

Przemysław Bielicki said...

No - I meant: return new Exception().getStackTrace()[0].toString();

Full stop!