// StackMethodExtractor.java import java.io.*; /** * Utility class with one public static method which returns the string name of * of a caller in the stack a given number of calls above the caller of that method. * It is very useful as a debugging aid. Many people like to use print statements as a * debugging aid. I generally don't, but on occasion it's useful to use a debugging * print statement as an initial stub implementation for a set of class or interface * methods. For example: <br><pre> * * class MyClass implements SomeInterface { * public void method1 { * System.out.println("method1 called"); * } * public void method2 { * System.out.println("method2 called"); * } * public void method3 { * System.out.println("method2 called"); * } * public void methodN { * System.out.println("methodN called"); * } * } * </pre></br> * * Pretty tedious, right? It's also error prone. Notice the deliberate cut-n-paste * error where interfaceImplemntation3 wrongly reports that implementation2 was called. * The solution using StackMethodExtractor is simply this: <br><pre> * * class MyClass implements SomeInterface { * public void method1 { * System.out.println(StackMethodExtractor.getCaller(0) + " called"); * } * public void method2 { * System.out.println(StackMethodExtractor.getCaller(0) + " called"); * } * public void method3 { * System.out.println(StackMethodExtractor.getCaller(0) + " called"); * } * public void methodN { * System.out.println(StackMethodExtractor.getCaller(0) + " called"); * } * } * </pre></br> * * This way all the initial implementations are identical. Easy to generate; totally * foolproof. Calling with an offset greater than zero returns method names that many * stack frames above your calling method. A somewhat more elegant means for seeing * where your code is being called from than <code>Thread.dumpStack()</code>. * * This is a refactored implementation of a more complicated utility by Ashutosh Marhari * published in Java Developer's Journal November 2001 volume 6 issue 11 page 56. * Note: the original source was supposed to be found at * http://www.sys-con.com/java/source2.cfm?volume=06&issue=11 * but seems to be missing. Ashutosh's email address is ashutosh@nahari.com * * @author Melinda Green - http://www.superliminal.com */ public class StackMethodExtractor { /** * A utility method which extracts the full name of a method on the stack * above the calling method. * @param callerID is the index of the method that many stack frames above the * calling method. The value 0 returns the name of the calling method itself, * 1 returns its immediate caller, 2 the caller of that caller, etc. * @return full name of the method calling this one a given number of stack * frames above that one. */ public static String getCaller(int callerID) { int stack_base = callerID + 2; // +1 to ignore "Thorwable" line, +1 to ignore this method StringWriter sw = new StringWriter(); (new Throwable()).printStackTrace(new PrintWriter(sw)); String trace = sw.toString(); int linestart = -1; for(int i=0; i<stack_base; i++) linestart = trace.indexOf("\n", linestart+1); return trace.substring(linestart+5, trace.indexOf("(", linestart+5)); } private static int countChars(char c, String str) { int count = 0; for(int i=0; i<str.length(); i++) if(str.charAt(i) == c) count++; return count; } /** * A simple example using StackMethodExtractor to print the name of the * VM method which is calling main. */ public static void main(String args[]) { System.out.println("main was called from: " + StackMethodExtractor.getCaller(1)); } }