File APIs for Java Developers
Manipulate DOC, XLS, PPT, PDF and many others from your application.
http://aspose.com/file-tools
The moose likes Java in General and the fly likes Who called? Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Java in General
Bookmark "Who called?" Watch "Who called?" New topic
Author

Who called?

Koen Aerts
Ranch Hand

Joined: Feb 07, 2012
Posts: 344

I have a method called "whoCalled". It returns the classname, methodname and line number of the method that called the original method. For instance say method A calls method B. If method B executes the whoCalled method, it will get the class/method name of method A.

Below is an example:


The output of above program is:

Basically in order to determine the calling method, I take the StackTrace (array of StackTraceElements) from a new Throwable instance, and return the 3rd item in that array (first item would the the whoCalled method itself, 2nd item the method that called it, etc.).

Are there other, perhaps more efficient or cleaner ways to achieve the same result, or is this it?
Jesper de Jong
Java Cowboy
Saloon Keeper

Joined: Aug 16, 2005
Posts: 14104
    
  16

As far as I know there isn't a much better / cleaner / more efficient way to do this.

I hope you're only using this for diagnostics (debug logging, for example). Your program will quickly become an entangled ball of spaghetti if the behaviour of methods changes depending on who's calling them. (You're adding nasty dependencies which will make the program very hard to understand).

Java Beginners FAQ - JavaRanch SCJP FAQ - The Java Tutorial - Java SE 7 API documentation
Scala Notes - My blog about Scala
Joanne Neal
Rancher

Joined: Aug 05, 2005
Posts: 3446
    
  12
There's no need to create the Throwable instance. The Thread class has a method for giving you a stack trace.


Joanne
Koen Aerts
Ranch Hand

Joined: Feb 07, 2012
Posts: 344

I tested the 2 different ways by timing "new Throwable()" vs "Thread.currentThread()" statements. It seems calling "new Throwable()" performs faster than "Thread.currentThread()" calls:

The result:

Not sure why that would be the case?
Paul Clapham
Bartender

Joined: Oct 14, 2005
Posts: 18541
    
    8

Or to convert that to the cost of a single call:



Or to put it another way, you're saving 0.8 microseconds by creating a new Throwable object. That doesn't seem like a savings I would be actively seeking, since presumably in real life you wouldn't be doing this process millions of times anyway. (Right?) However you haven't included the cost of having that Throwable object garbage-collected, so your savings are less than 0.8 microseconds per call and possibly even negative.
Joanne Neal
Rancher

Joined: Aug 05, 2005
Posts: 3446
    
  12
Paul Clapham wrote:Or to convert that to the cost of a single call:



Or to put it another way, you're saving 0.8 microseconds by creating a new Throwable object. That doesn't seem like a savings I would be actively seeking, since presumably in real life you wouldn't be doing this process millions of times anyway. (Right?) However you haven't included the cost of having that Throwable object garbage-collected, so your savings are less than 0.8 microseconds per call and possibly even negative.

Except that the Thread method does this

which means they are doing the same thing except the Thread method checks if the thread it's being called on is the current thread which I assume is what causes it to be slighly slower
Koen Aerts
Ranch Hand

Joined: Feb 07, 2012
Posts: 344

The differences are probably negligible enough to be ignored. I just like to understand why things behave the way they do. For instance I had found that the String compareTo method is slighty faster than the equals method, however the equalsIgnoreCase method is significantly slower than equals.
Jesper de Jong
Java Cowboy
Saloon Keeper

Joined: Aug 16, 2005
Posts: 14104
    
  16

Koen Aerts wrote:The differences are probably negligible enough to be ignored. I just like to understand why things behave the way they do. For instance I had found that the String compareTo method is slighty faster than the equals method, however the equalsIgnoreCase method is significantly slower than equals.

Micro-benchmarking is very difficult to do correctly on the JVM.

The JIT (Just In Time) compiler, that compiles Java bytecode to native machine code at runtime, contains many very sophisticated optimizations. It contains complicated logic to determine when to compile what parts of the code to native machine code, does inlining and a whole list of other optimizations, and can even in some special cases de-optimize code and then recompile it again to machine code.

Simply calling a method N times and measuring how long it takes often doesn't give you a timing number that's accurate to the last digit. It depends heavily on what decisions the JIT makes and can be different on different machines, at different times or across different JVM versions.

If you know what the methods of the String class do exactly, you could lookup the source code of class String; you'll find the source code in the file src.zip in your JDK installation directory.
Campbell Ritchie
Sheriff

Joined: Oct 13, 2005
Posts: 38340
    
  23
You ought to use the nanoseconds method of the System class. And you will find that performance varies considerably on repeated runs.
Winston Gutkowski
Bartender

Joined: Mar 17, 2011
Posts: 7639
    
  19

Campbell Ritchie wrote:You ought to use the nanoseconds method of the System class. And you will find that performance varies considerably on repeated runs.

Except that System.nanoTime() takes about 5 times as long to run as System.currentTimeMillis() (at least on my machine).

Good old Heisenberg

Winston


Isn't it funny how there's always time and money enough to do it WRONG?
Articles by Winston can be found here
Campbell Ritchie
Sheriff

Joined: Oct 13, 2005
Posts: 38340
    
  23
Earlier, I wrote: . . . you will find that performance varies considerably on repeated runs.
See, told you so.
Koen Aerts
Ranch Hand

Joined: Feb 07, 2012
Posts: 344

Jesper de Jong wrote:
Koen Aerts wrote:The differences are probably negligible enough to be ignored. I just like to understand why things behave the way they do. For instance I had found that the String compareTo method is slighty faster than the equals method, however the equalsIgnoreCase method is significantly slower than equals.

Micro-benchmarking is very difficult to do correctly on the JVM.

That's true. And I did find that consecutive runs give slightly different results each time; however I do think in some cases it provides useful information, especially in cases where the performance difference between similar functions is fairly large. For instance 1 billion iterations over the String equals() method took about 500ms, but about 27 seconds for the equalsIgnoreCase() method. But you're right; millisecond differences are probably in most cases negligible.
Randall Twede
Ranch Hand

Joined: Oct 21, 2000
Posts: 4340
    
    2

don't you listen to them Koen. you had it pretty right from the start


SCJP
Visit my download page
Paul Clapham
Bartender

Joined: Oct 14, 2005
Posts: 18541
    
    8

Following on from what Jesper mentioned about the JIT: if you're going to do a micro-benchmark where you time A and then time B, you should also do a similar micro-benchmark where you time B and then time A. That's because the JIT will wait for a while before it starts optimizing your code, so that earlier code can be less optimized.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Who called?