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: 471
/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.Exception
as 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