Java stack traces in Emacs compilation-mode

I often run Java programs like Android apps in my Emacs compilation buffer while I’m working on them, so I see Java stack traces there just like compile errors. Emacs is good at identifying compilation errors so you can jump straight to the source file and line, but not so much with stack traces.

Here’s an elisp snippet that adds stack trace support, so you can jump to individual lines with C-x `, mouse click, or next-error:

(defvar java-stack-trace-dir "src/")
(defun java-stack-trace-regexp-to-filename ()
  "Generates a relative filename from java-stack-trace regexp match data."
  (concat java-stack-trace-dir
          (replace-regexp-in-string "\\." "/" (match-string 1))
          (match-string 2)))

(add-to-list 'compilation-error-regexp-alist 'java-stack-trace)
(add-to-list 'compilation-error-regexp-alist-alist
  '(java-stack-trace .
    ("^[[:space:]]*at \\(\\(?:[[:lower:]]+\\.\\)+\\)[^(]+(\\([[:alnum:]]+\\.java\\):\\([[:digit:]]+\\))"
     java-stack-trace-regexp-to-filename 3)))

You can customize java-stack-trace-dir to set the base directory to search for source files. If it’s relative, it will be appended to the compilation’s working directory.

Happy hacking!

2 thoughts on “Java stack traces in Emacs compilation-mode

  1. Thanks for the excellent information! I ran into a few issues with this implementation:

    1. the test runner might add text before the “at”. Which causes the ^[[:space:]] chunk to fail to match.
    2. the [[:lower:]] character class really only matters if regexps are in case sensitive mode. By default this is not the case.
    3. Test files, in my case, are placed under a different folder than package sources.

    I modified the above implementation to resolve both:

    I’m an emacs noob so there is rampant copy pasta in that file.

    The regex that worked for me for just package sources:

    (add-to-list ‘compilation-error-regexp-alist-alist ‘(java-stack-trace . (“at \\(\\(?:[[:alnum:]]+\\.\\)+\\)+[[:alnum:]]+\\.[[:alnum:]]+(\\([[:alnum:]]+\\.java\\):\\([[:digit:]]+\\))$” java-stack-trace-regexp-to-filename 3)))

Leave a Reply

Your email address will not be published.