Recommended: Sing it, brah! 5 fabulous songs for developers
JW's Top 5
Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs
Page 2 of 4
To extract and display the mapping information, the example code uses a helper method, displayStackTraceInformation(), with the following basic usage idiom:
//...
public void crashAndBurnout()
{
//...
displayStackTraceInformation (new Throwable());
//...
}
//...
The displayStackTraceInformation() code is pretty straightforward:
public static boolean displayStackTraceInformation (Throwable ex,
boolean displayAll)
{
if (null == ex)
{
System.out.println ("Null stack trace reference! Bailing...");
return false;
}
System.out.println ("The stack according to printStackTrace():\n");
ex.printStackTrace();
System.out.println ("");
StackTraceElement[] stackElements = ex.getStackTrace();
if (displayAll)
{
System.out.println ("The " + stackElements.length +
" element" +
((stackElements.length == 1) ? "": "s") +
" of the stack trace:\n");
}
else
{
System.out.println ("The top element of a " +
stackElements.length +
" element stack trace:\n");
}
for (int lcv = 0; lcv < stackElements.length; lcv++)
{
System.out.println ("Filename: " +
stackElements[lcv].getFileName());
System.out.println ("Line number: " +
stackElements[lcv].getLineNumber());
String className = stackElements[lcv].getClassName();
String packageName = extractPackageName (className);
String simpleClassName = extractSimpleClassName (className);
System.out.println ("Package name: " +
("".equals (packageName)?
"[default package]" : packageName));
System.out.println ("Full class name: " + className);
System.out.println ("Simple class name: " + simpleClassName);
System.out.println ("Unmunged class name: " +
unmungeSimpleClassName (simpleClassName));
System.out.println ("Direct class name: " +
extractDirectClassName (simpleClassName));
System.out.println ("Method name: " +
stackElements[lcv].getMethodName());
System.out.println ("Native method?: " +
stackElements[lcv].isNativeMethod());
System.out.println ("toString(): " +
stackElements[lcv].toString());
System.out.println ("");
if (!displayAll)
return true;
}
System.out.println ("");
return true;
} // End of displayStackTraceInformation().
Basically, we call getStackTrace() on the passed-in Throwable, and then loop through the individual StackTraceElements, extracting as much mapping information as possible.
Note the bit of cruft the displayAll parameter introduces. displayAll lets the calling site decide whether or not to display all the StackTraceElements or just the stack's topmost element. The example program uses the displayAll parameter to restrict the output to a reasonable amount.
Most of the stack trace information is directly useful. For example, the StackTraceElement.getMethodName() returns a string that contains the method name, while StackTraceElement.getFileName() returns a string with the original source filename. Read the StackTraceElement Javadoc for the complete list of methods.
As you probably noticed, the displayStackTraceInformation() code uses several additional helper methods to pull apart the value returned by StackTraceElement.getClassName(). Those helper methods are needed because StackTraceElement.getClassName() returns the class's fully qualified name, and StackTraceElement has no other methods to provide the underlying parts of the fully qualified class name. We'll learn about each additional
helper method by working through the various example uses of displayStackTraceInformation().
Given the fully qualified class name, extractPackageName() gives the name of the package in which the class resides:
public static String extractPackageName (String fullClassName)
{
if ((null == fullClassName) || ("".equals (fullClassName)))
return "";
int lastDot = fullClassName.lastIndexOf ('.');
if (0 >= lastDot)
return "";
return fullClassName.substring (0, lastDot);
}
Basically, extractPackageName extracts everything preceding the last dot in the fully qualified class name. That preceding information just happens to
be the package's name.
Note: You can comment/uncomment the package statement at the top of StackTrace.java to explore the difference between running the example program in the default, unnamed package versus running it in the boo.hoo package. For example, when uncommented, the display of the topmost stack element for the call to bar() from foo() from main() should look like this:
Filename: StackTrace.java Line number: 227 Package name: boo.hoo Full class name: boo.hoo.StackTrace Simple class name: StackTrace Unmunged class name: StackTrace Direct class name: StackTrace Method name: bar Native method?: false toString(): boo.hoo.StackTrace.bar(StackTrace.java:227)
Alternatively, if you comment out the package statement, then the above stack element should resemble this:
Filename: StackTrace.java Line number: 227 Package name: [default package] Full class name: StackTrace Simple class name: StackTrace Unmunged class name: StackTrace Direct class name: StackTrace Method name: bar Native method?: false toString(): StackTrace.bar(StackTrace.java:227)
The next helper method we use is extractSimpleClassName(). As you'll see, that method's results are not necessarily simple, but I want to clearly distinguish this simplified class
name from the fully qualified class name.
Basically, extractSimpleClassName() complements extractPackageName():
public static String extractSimpleClassName (String fullClassName)
{
if ((null == fullClassName) || ("".equals (fullClassName)))
return "";
int lastDot = fullClassName.lastIndexOf ('.');
if (0 > lastDot)
return fullClassName;
return fullClassName.substring (++lastDot);
}
In other words, extractSimpleClassName() returns everything after the last dot (.) from the fully qualified class name. For example, from the same call to bar() above, we see that the simple class name is just StackTrace, whether or not the code is part of the default package or a named package.
We get more interesting results when we turn our attention to nested classes. In the example program, I created two levels
of nested, named classes (FirstNested and FirstNested.SecondNested) along with an additional, anonymous inner class (inside FirstNested.SecondNested).
The whole nested usage starts with:
public StackTrace (boolean na)
{
StackTrace.FirstNested nested = new StackTrace.FirstNested();
}
Note that the boolean parameter (na) means nothing. I just added it since other constructors need to be distinguished.
StackTrace.javajava.lang.ThrowablegetStackTrace()java.lang.StackTraceElementjava.util.logging package