Hidden exceptions
Posted
by user12617285
on Oracle Blogs
See other posts from Oracle Blogs
or by user12617285
Published on Wed, 22 Jun 2011 05:25:29 -0700
Indexed on
2011/06/22
16:26 UTC
Read the original article
Hit count: 563
/Sun
Occasionally you may find yourself in a Java application environment where exceptions in your code are being caught by the application framework and either silently swallowed or converted into a generic exception. Either way, the potentially useful details of your original exception are inaccessible. Wouldn't it be nice if there was a VM option that showed the stack trace for every exception thrown, whether or not it's caught? In fact, HotSpot includes such an option: -XX:+TraceExceptions. However, this option is only available in a debug build of HotSpot (search globals.hpp for TraceExceptions). And based on a quick skim of the HotSpot source code, this option only prints the exception class and message. A more useful capability would be to have the complete stack trace printed as well as the code location catching the exception. This is what the various TraceException* options in in Maxine do (and more). That said, there is a way to achieve a limited version of the same thing with a stock standard JVM. It involves the use of the -Xbootclasspath/p non-standard option. The trick is to modify the source of java.lang.Exception by inserting the following:
private static final boolean logging = System.getProperty("TraceExceptions") != null;
private void log() {
if (logging && sun.misc.VM.isBooted()) {
printStackTrace();
}
}
Then every constructor simply needs to be modified to call log() just before returning:
public Exception(String message) {
super(message);
log();
}
public Exception(String message, Throwable cause) {
super(message, cause);
log();
}
// etc...
You now need to compile the modified Exception.java source and prepend the resulting class to the boot class path as well as add -DTraceExceptions to your java command line. Here's a console session showing these steps:
% mkdir boot
% javac -d boot Exception.java
% java -DTraceExceptions -Xbootclasspath/p:boot -cp com.oracle.max.vm/bin test.output.HelloWorld
java.util.zip.ZipException: error in opening zip file
at java.util.zip.ZipFile.open(Native Method)
at java.util.zip.ZipFile.(ZipFile.java:127)
at java.util.jar.JarFile.(JarFile.java:135)
at java.util.jar.JarFile.(JarFile.java:72)
at sun.misc.URLClassPath$JarLoader.getJarFile(URLClassPath.java:646)
at sun.misc.URLClassPath$JarLoader.access$600(URLClassPath.java:540)
at sun.misc.URLClassPath$JarLoader$1.run(URLClassPath.java:607)
at java.security.AccessController.doPrivileged(Native Method)
at sun.misc.URLClassPath$JarLoader.ensureOpen(URLClassPath.java:599)
at sun.misc.URLClassPath$JarLoader.(URLClassPath.java:583)
at sun.misc.URLClassPath$3.run(URLClassPath.java:333)
at java.security.AccessController.doPrivileged(Native Method)
at sun.misc.URLClassPath.getLoader(URLClassPath.java:322)
at sun.misc.URLClassPath.getLoader(URLClassPath.java:299)
at sun.misc.URLClassPath.getResource(URLClassPath.java:168)
at java.net.URLClassLoader$1.run(URLClassLoader.java:194)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at sun.misc.Launcher$ExtClassLoader.findClass(Launcher.java:229)
at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
at java.lang.ClassLoader.loadClass(ClassLoader.java:295)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
java.security.PrivilegedActionException
at java.security.AccessController.doPrivileged(Native Method)
at sun.misc.URLClassPath$JarLoader.ensureOpen(URLClassPath.java:599)
at sun.misc.URLClassPath$JarLoader.(URLClassPath.java:583)
at sun.misc.URLClassPath$3.run(URLClassPath.java:333)
at java.security.AccessController.doPrivileged(Native Method)
at sun.misc.URLClassPath.getLoader(URLClassPath.java:322)
...
It's worth pointing out that this is not as useful as direct VM support for tracing exceptions. It has (at least) the following limitations:
- The trace is shown for every exception, whether it is thrown or not.
- It only applies to subclasses of
java.lang.Exceptionas there appears to be bootstrap issues when the modification is applied toThrowable.java. - It does not show you where the exception was caught.
- It involves overriding a class in rt.jar, something should never be done in a non-development environment.
© Oracle Blogs or respective owner