On this page, you'll learn how you can:
- Get method autocompletion
- Get on the fly syntax checking
- Do remote debugging
- Get Maven support
- Get Ant support
- Edit all Java related XML formats
- Make Emacs jump to the source of a given class
- Get Emacs to import missing classes
- Get Emacs to override a method
- Generate sensible JavaDoc for your methods and classes.
- Run JUnit tests
The bear necessities for any java developer is syntax highlighting, autocompletion of methods and a class browser. Luckily enough, Emacs provides them all
A well kept secret, is that it's possible to achieve on the
fly syntax checking of your Java code using The Eclipse
compiler and Emacs' built-in
I was first made aware of this thanks to Arjen Wiersma's excellent blog post
Emacs can quite comfortably do debugging of Java applications running on remote JVMs using the excellent JDIbug.
JDEE provides two other means to debug applications, but I would recommend JDIbug any day of the week. It's fast and provides a visual tree of variables. Currently (2009-07-18 13:06), it has one drawback; it cannot debug inner classes, but I'm sure this is something that will be remedied in a later release.
Given that you have the given source code in the
jde-sourcepath variable, you can browse the call
stack leading up to the break point. Here, I am browsing the
state of one of Tomcat's classes when executing my
As a Java developer you're most probably using Maven to build, package and
releaese software. Thanks to nxml-mode,
Emacs provides auto completion of tags and on the fly syntax
checking of your
To compile projects from within Emacs, I've bound Emacs'
compile command to
C-z. This is
personal preference of course, but I far more often want to
compile my software than minimise Emacs (which is the default
Here, I am compiling my project using Maven. Compilation
errors are given as links that will take you to the line and
column in the source file where the error is. As with all
compile buffers in Emacs, you can jump to the
next error by hittihg
C-` (very easy shortcut on
an American keyboard, on e.g. Norwegian or German it's not,
hence I recommend using American keyboard layout for
Emacs will happily allow you to compile Ant projects with jump
to error links (as shown above with Maven projects) and edit
As a Java developer, you're most likely to also want support for the following XML formats:
Luckily, this is a doodle for Emacs, as long as it has everything's setup correctly.
Override any of the parent class(es)' methods by hitting
C-c C-v o. Emacs will then let you
TAB complete your way through the available
Emacs will jump to the source of the class at point or where
the variable is instantiated when you hit
Emacs can either import the class where your cursor is by
C-c C-v C-z or import all classes missing
from the import list by hitting the (almost identical)
C-c C-v z
Emacs will implement any interface that in its
jde-global-classpath variable (or
C-x C-v i and
TAB-complete your way to the interface and hit
ENTER. Emacs will then generated method stubs of
all the interface methods.
How to set it all up
Okay, now I've shown you what you get, now I show you what you need to get it
Using Debian based systems
# apt-get install sun-java6-bin emacs22 nxml-mode jde ecb ecj
Currently (2009-07-18 16:12), there's no Debian package for JDIbug, so you must download it from code.google.com/jdibug
If you're using a different system
The packages may or may not be available through the system's package manager (the BSDs, Open Solaris and GNU/Linux distributions have this, Windows, Mac and Sun Solaris doesn't).
To manually install the needed software packages, download them from the these addresses:
- GNU Emacs
- Sun's Java Development Kit
- Java Development Environment for Emacs
- Emacs Code Browser
- The Eclipse Java Compiler
Java related Emacs settings
This is my Java hook, giving me:
- two space indent
mvn compilein my project.
M-ndoes autocompletion of Java methods using the mini buffer (fastest).
M-Ndoes autocompletion of Java methods using the (GTK) menu (slower, but nicer).
C-c C-njumps to next/previous compile error or warning given by the Eclipse compiler.
switch/casestatements looks the way I want, i.e. indents the
switchcontents like any other block.
(defun my-c-mode-hook () (setq c-basic-offset 2 c-label-offset 0 indent-tabs-mode nil compile-command "cd ~/projects/myproject; mvn compile" require-final-newline nil) (lambda () (auto-fill-mode 1)) (define-key c-mode-base-map "\C-m" 'c-context-line-break) (global-set-key "\M-n" 'jde-complete-minibuf) (global-set-key "\M-N" 'jde-complete-menu) (define-key c-mode-base-map "\C-c\C-p" 'show-previous-error) (define-key c-mode-base-map "\C-c\C-n" 'show-next-error) (c-set-offset 'substatement-open 0)) (add-hook 'c-mode-common-hook 'my-c-mode-hook)
Understanding compiler output
(require 'compile) (setq compilation-error-regexp-alist (append (list ;; works for jikes '("^\\s-*\\[[^]]*\\]\\s-*\\(.+\\):\\([0-9]+\\):\\([0-9]+\\):[0-9]+:[0-9]+:" 1 2 3) ;; works for javac '("^\\s-*\\[[^]]*\\]\\s-*\\(.+\\):\\([0-9]+\\):" 1 2) ;; works for maven '("^\\(.*\\):\\[\\([0-9]*\\),\\([0-9]*\\)\\]" 1 2 3)) compilation-error-regexp-alist))
Setting up JDIbug
Add this to your
.emacs, adjusting the path to
jdibug to where you have your copy.
(add-to-list 'load-path "/usr/local/src/jdibug") (require 'jdibug)
Be sure to start the app server with the following JVM
-Xdebug -Xnoagent -Djava.compiler=NONE
If you're using Apache
Tomcat, you can set the
$ export CATALINA_OPTS="-Xdebug -Xnoagent -Djava.compiler=NONE \ -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=6001" $ ./tomcat/bin/catalina.sh start
Nedless to say, you will soon put this in a script instead of typing it every time you start the app server
Setting up flymake and ejc
This configuration is taken from Arjen Wiersma's excellent
blog post, I have modified it a wee bit (using the
ecj BASH script instead of calling the JAR
directly) and added two methods for jumping to next/previous
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Java flymake support using the Eclipse compiler ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (require 'flymake) (defun flymake-java-ecj-init () (let* ((temp-file (flymake-init-create-temp-buffer-copy 'jde-ecj-create-temp-file)) (local-file (file-relative-name temp-file (file-name-directory buffer-file-name)))) ;; if you've downloaded ecj from eclipse.org, then use these two lines: ;; (list "java" (list "-jar" ;; "/usr/share/java/ecj.jar" ;; if installing it with DEB packages,or by some other means ;; giving you the ecj BASH script front end, simply use this line ;; instead: (list "ecj" (list "-Xemacs" "-d" "/dev/null" "-source" "1.5" "-target" "1.5" "-sourcepath" (car jde-sourcepath) "-classpath" (jde-build-classpath jde-global-classpath) local-file)))) (defun flymake-java-ecj-cleanup () "Cleanup after `flymake-java-ecj-init' -- delete temp file and dirs." (flymake-safe-delete-file flymake-temp-source-file-name) (when flymake-temp-source-file-name (flymake-safe-delete-directory (file-name-directory flymake-temp-source-file-name)))) (defun jde-ecj-create-temp-file (file-name prefix) "Create the file FILE-NAME in a unique directory in the temp directory." (file-truename (expand-file-name (file-name-nondirectory file-name) (expand-file-name (int-to-string (random)) (flymake-get-temp-dir))))) (push '(".+\\.java$" flymake-java-ecj-init flymake-java-ecj-cleanup) flymake-allowed-file-name-masks) (push '("\\(.*?\\):\\([0-9]+\\): error: \\(.*?\\)\n" 1 2 nil 2 3 (6 compilation-error-face)) compilation-error-regexp-alist) (push '("\\(.*?\\):\\([0-9]+\\): warning: \\(.*?\\)\n" 1 2 nil 1 3 (6 compilation-warning-face)) compilation-error-regexp-alist) (defun credmp/flymake-display-err-minibuf () "Displays the error/warning for the current line in the minibuffer" (interactive) (let* ((line-no (flymake-current-line-no)) (line-err-info-list (nth 0 (flymake-find-err-info flymake-err-info line-no))) (count (length line-err-info-list)) ) (while (> count 0) (when line-err-info-list (let* ((file (flymake-ler-file (nth (1- count) line-err-info-list))) (full-file (flymake-ler-full-file (nth (1- count) line-err-info-list))) (text (flymake-ler-text (nth (1- count) line-err-info-list))) (line (flymake-ler-line (nth (1- count) line-err-info-list)))) (message "[%s] %s" line text) ) ) (setq count (1- count))))) (defun show-previous-error () (interactive) (flymake-goto-prev-error) (credmp/flymake-display-err-minibuf)) (defun show-next-error () (interactive) (flymake-goto-next-error) (credmp/flymake-display-err-minibuf))