When working with JSP or with other languages that are converted to Java source code (or to stubs), there is often a SMAP file generated which can be later embedded to the Class file for debuggers to show better stack traces (or in case of Jasper it gets embedded automatically).
There is an old JVM bug (or RFE) to add support to include SMAP information in stack traces, but from lack of activity it seems the Sun/Oracle guys prefer that everyone post-processes his stack traces himself.
So here is my question: How to do this? Are there libraries around that do the hard work for you, or do you have to implement everything yourself?
I already found a good place where I have access to both the exception object and the class loader that loaded the "SMAP enabled" classes. Now I’d have to
- iterate over the stack trace
- Check for each entry if I can find the class
- Analyze the class with e. g. ASM to extract the SMAP info
- Write a SMAP parser that parses the reverse line mapping and the file names out of the SMAP info
- Replace the stack trace element by a new one based on the mapping (or alternatively add a new one? What is better?)
- Cache some of the info so that I don’t have to do the same stuff again if the exact same (or a similar) stack trace re-appears a few seconds later.
And since it seems to be a tedious and error-prone task, I’m hoping that someone already did this and I just have to add a library to my dependencies and call a makeStacktraceFancy method for my exceptions to make the stacktraces fancy before I log them.
As no one seems to know of an existing solution, I rolled my own quick&dirty one.
It does not support all SMAP features (it parses only the first stratum, and ignores vendor sections and default statum information), but it is enough for my needs.
Since the code to extract the SMAP attribute from the class is only about 50 lines, I decided to reimplement it instead of adding ASM as a dependency. The code for how to use it with ASM is in the comments.
As it is only tested very little (on a few test cases), I’ll edit the post if I encounter any severe errors.
Code is below: