Laboratory: Using JDE
CSC 207 Algorithms and Object Oriented Design Spring 2011

Summary: In this lab, you will learn how to configure the Java Development Environment for Emacs (JDEE or just JDE) and use its built-in debugger.

Preparation

  1. Make a directory for the code you will be using in this lab:
      mkdir somewhere/jdelab
      cd somewhere/jdelab
  2. Copy the source files for this lab to your new directory:
      cp ~weinman/public_html/courses/CSC207/2011S/labs/code/jde/Factorial.java .
      cp ~weinman/public_html/courses/CSC207/2011S/labs/code/jde/Fibonacci.java .
                

Exercises

Exercise 1

  1. Edit (or create) a configuration file for emacs in your home directory:
      emacs ~/.emacs & 
  2. Add the following lines to your .emacs file.
    dotemacs.el
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    ;; JDE Configuration Commands
    
    ;; Include the speedbar (GNU emacs)
    (unless (string-match "XEmacs" emacs-version)
      (define-key-after (lookup-key global-map [menu-bar tools])
        [speedbar] '("Speedbar" . speedbar-frame-mode) [calendar])
    )
    
    ; Include pwd of a source file in the sourcepath for compilation
    (setq jde-sourcepath (quote (".")))       
    
    ;; Include pwd of a source file in the classpath for compilation
    (setq jde-global-classpath (quote ("."))) 
    
    ; Always include debug info when using JDE to compile
    (setq jde-compile-option-command-line-args (quote ("-g")))
    
    ; Tell JDE where to find the JDK (i.e., javac, java, and jdb)
    (setq jde-jdk-registry 
          (quote (("1.6" . "/usr/lib/jvm/java-6-openjdk"))))
    
    ; Tell JDE which JDK to use
    (setq jde-jdk (quote ("1.6")))
    
    ; In case we use emacs for other things, delay the (lengthy) loading
    ; of JDE until a Java file is actually opened
    (setq defer-loading-jde t)
    (if defer-loading-jde 
        (progn
          (autoload 'jde-mode "jde" "JDE mode." t)
          (setq auto-mode-alist
                (append 
                 '(("\\.java\\'" . jde-mode))
                 auto-mode-alist)))
      (require 'jde))
    
    ;;  JDE Config
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Exercise 2

If you already had a .emacs file, you may want to check and see whether the commands you'll add in this exercise are already present. It won't harm anything to add them twice, but there's certainly no need to .
  1. Add the following lines to enable syntax highlighting on any file you open in Emacs:
    ;; Enable syntax highlighting
    (global-font-lock-mode t)
  2. Add the following lines to enable parenthesis/brace matching in your source code (very handy!)
    ;; Show matching paren or bracket when cursor is on or after it
    (show-paren-mode 1)
  3. Close emacs.

Exercise 3

  1. Open the file Factorial.java in Emacs. This should cause syntax highlighting to automatically come on (if it didn't already), and you might also notice it will take slightly longer to load, because the Java Development Environment is being loaded.
  2. You should see several new menus appear at the top of Emacs. Specifically:
    • Classes
    • JDE
    • Java
    • Jdb
  3. Click on the menu Classes. What does it show you? What happens if you choose a function name from the drop down menus?
  4. Add a class variable to Factorial.java:
      private static String foo;
  5. Now click on the Classes menu again. What is different about it? Does clicking on different things from the menu give you the behavior you might expect?
  6. Click on the JDE menu and examine some of the options in the menu and its submenus.
  7. Place your cursor somewhere on the line for your new variable foo. Click on the menu JDE ~ Documentation ~ Add. What happens?

    Note that you can accomplish the same thing with C-c C-v j (which means type Control-c, Control-v, and then j). Starting documentation is this easy. You have no excuses henceforth.

  8. Now, place your cursor at the end of the line for your variable foo. Click on the menu JDE ~ Code Generation ~ Wizards ~ Generate Get/Set Methods. What happens?
  9. Do your new methods show up in the Classes menu?

Exercise 4

  1. Inside one of the methods you just created, add a new line beginning
     foo.s
    as if you were going to call a member method of the variable foo that starts with s
  2. With the cursor still placed right after the s, type C-c C-v C-. (that is, control-C, control-V, and control-. (period)). What happens?
  3. Explore the menu(s).
  4. Find the entry
    subSequence(int, int) : java.lang.CharSequence
    and select it.
  5. What do you suppose are the arguments to this method? What is the return type?
  6. Delete what was just added and add an e so that you are left with just
    foo.e
    with the cursor placed just after the e.
  7. Do another "auto-complete" (C-c C-v C-.)
  8. How are the options different? Are they consistent with what you'd already typed?
This so-called auto-completion of fields (member variables) or methods is one of the most convenient properties of an integrated development environment, such as JDE. In JDE, auto-complete will work with any Java API type or a type you have defined, so long as In addition, methods of the current object can be autocompleted if they are preceded by a this., super. or even just a . prefix (though the latter is not acceptable syntax).

Exercise 5

  1. Open the Speedbar by going to the menu Tools ~ Speedbar. A new window should appear near your emacs frame that shows the files in your current directory.
  2. Notice that each file has a [+] next to it, indicating that it can be "opened," just like folders in many file browsers. Using your middle mouse button (which may be a wheel), click on the [+] next to Factorial.java. What do you see?
  3. The speedbar understands Java (and many other kinds of files). What appears is a list of the classes inside the file you "opened." Middle-click again on the +> to "open" that class and see what's inside.
  4. Middle-click on the +> next to foo. What appears? Suppose you hadn't added that variable but were investigating someone else's code (or code that you had written long ago). Do you suppose easily accessing this information could be useful?
  5. Middle-click on the {+} next to Methods. It should not be too surprising what you see.
  6. What do you expect to appear when you open a method? (What might one want to know about a method?)
  7. Open (by middle-clicking the +> next to it) the method setFoo(). What appears? Is there anything new that appears you can also open? If so, open it! Does it show what you might expect?
  8. Now, "close" the Methods section by middle-clicking on the {-} next to it, and then reopen it. You can decide whether or not you like this amnestic feature.
  9. In the speedbar, middle click on the method calc() (that is, on the name itself, not the +> next to it). What happens?
  10. What do you suppose happens if you click on the variable foo in the Speedbar? Try it and see!
  11. Hopefully by now you should see that the Speedbar, which functions as your code navigator, can be very handy, especially when you've got much bigger files (which of course shouldn't be too big, because that would violate the tenets of OOP!), with many methods and variables.

Exercise 6

  1. Now that we've spent all this time poking around the code, let's try to compile and run it! Go to the menu JDE and choose Compile. (If you haven't already saved the modifications you've made, it will probably ask you to. Go ahead and save them.)
  2. You should see a new buffer appear that shows the result of compiling the class. Hey, no more hunting for a terminal and typing javac what-was-my-file-again! (That is, unless you prefer to.)
  3. If your class has a static main method, you can also run the program from within emacs. Click on JDE ~ Run App. What do you see?
  4. Ok, so if your program requires interactivity, that doesn't exactly work. You'll still have to remember where it is and go run java manually.
  5. Go back to your command line and run the program
      java Factorial n
    for some small values of n (e.g. 3-6). Do these agree with what you know about the factorial function?
  6. Run the program with n equal to 9. Does this give you an answer you expect?
  7. Why do you suppose the program outputs the result you're getting? Perhaps it's already quite obvious, but if it weren't, in the next exercise we'll do a little poking that may help shed some light on the matter.

Exercise 7

One of the greatest things about a debugger is that it allows you to inspect variables, and step through code one line (or operation) at a time. In this exercise, we'll look at JDE's methods for doing this.
  1. In the source file for Factorial.java, place the cursor on the line inside main that declares facArg.
  2. If the debugger is going to allow us to step through code line by line, it might be very tedious for us to step through many lines before we reach the one we're interested in. Therefore, we can set what are called breakpoints. The program may continue its normal behavior until it reaches one of these breakpoints, and then we have the option of inspecting some variables, stepping, and/or telling the program continue (perhaps until it reaches another breakpoint).

    With your cursor at the aforementioned line, go to the Jdb menu and select "Toggle Breakpoint". You should see the breakpointed line change to green. We can set as many breakpoints as we like, but for now we'll stick with this one.

  3. Now let's run our program in debug mode. Go to the JDE menu and choose Debug App. Your emacs frame should split in two, and in the top half you should see the main function, and in the bottom half the debugger output.
  4. The debugger has actually begun running your program, and it should have hit the breakpoint you set for it, which is why the breakpoint line should be yellow and have a little right-facing arrow next to it on the left side.
  5. When JDE started the debugger for you, it also transferred the cursor to that buffer. Let's make sure we can see the updates from the debugger as they are happening by placing the cursor at the end of this buffer. You can do this by pressing the End key on your keyboard (assuming you still have the cursor focus in the bottom frame).
  6. Return the cursor to the Java file (either by clicking, or using C-x o. Now you can step the debugger, but we have a few options for stepping. Let's explore each in turn.
  7. From the Jdb menu, choose Step Over. (Or you may type the shortcut C-c C-a C-s. What happens to the cursor next to the breakpoint line? What do you see in the debugger buffer below?
  8. Do a Step Over again (either from the menu or the keyboard shortcut). Where is the arrow now? You should see it next to the expression printUsage();. The arrow indicates the next line that will be executed when we continue stepping.
  9. Step Over one more time. What appears in the debugger window?
  10. The program ended up running the printUsage();, which results in termination. The debugger communicates this to us by saying "The application exited."
  11. Now let's try a different version of "stepping." Return the cursor to the Java file and start the debug process again with JDE ~ Debug App. This should leave us at our breakpoint once again, with the debugger output below. Don't forget to make sure that you're seeing the most recent output by going to the debugger buffer and pressing the "End" key.
  12. Return to the Java window, and this time use the command Jdb ~ Step Into (or the keyboard equivalent C-c C-a C-n). Do you notice anything different?
  13. Do another Step Into. Presumably, the arrow (indicating the next expression) has moved along happily down the code and should now once again be pointing at the printUsage(); expression.
  14. Do yet another Step Into. Now what happens? Where in the code are you?
  15. Describe the difference between stepping "over" and stepping "into" a function call.

Exercise 8

Clearly, if we are going to do any useful debugging, we are going to want our program to accept command line arguments. Fortunately, JDE has provided a way to do this. We are going to do it two ways, one that only affects our current emacs session (so that we don't have to quit and restart emacs), and another that makes the change "permanent" (or at least automatic) in our .emacs file
  1. Type M-x set-variable (the M means the "meta" key which is usually Alt or Esc).
  2. At the Set variable: prompt, type jde-db-read-app-args and press enter.
  3. At the Set jde-db-read-app-args to value: prompt, type t and press enter. These steps should take care of your current session.
  4. To make this behavior permanent (you can always type nothing when the debugger asks you for command line arguments), add the following line to your .emacs file with the other JDE configuration lines.
    ;; Read command line arguments for debugging
                      (setq jde-db-read-app-args t)
  5. Now when you go to JDE ~ Debug App you should get a prompt (at the bottom, in what is called the "minibuffer" window) for Application args: . Here you would type the normal command line arguments that would ordinarily follow java Factorial, or whatever the command line invocation may be for your program.
  6. Type 9 (the input that gives us a strange factorial), and press enter.

Exercise 9

  1. Now that you have entered some command line arguments, the program should proceed without error past all the command-line procesing steps. Do a Step Into until you are actually at the first line of the calc method.
  2. Before you step any further, go to the Jdb menu and select Display ~ Locals. What do you see in the debugger window?
  3. Now take one more step (either step into or step over should achieve the same thing, since the variable declaration does not involve a function call). Display the local variables once again (the keyboard shortcut is C-c C-a C-l. Do you see anything different in the debugger window?
  4. The white arrow should now be at the left of the for loop. Take one more step and then display the local variables once again. Now what has been added in the debugger window?
  5. Take another step and display the locals. Has any thing changed?
  6. Continue to step over these two lines of code and watch the variables. For what value of i do things begin to go "haywire"?
  7. To exit the debugger, you can simply go to that window and close it like you would any other file (i.e., C-x k). Go ahead and close it now.
  8. In case you don't remember you can get back to "one window" in your emacs frame by typing C-x 1. Do that now.

Exercise 10

If you want to use command line arguments to run the program from within JDE normally (without debugging), repeat the details of Exercise 8, replacing the variable name jde-db-read-app-args with jde-run-read-app-args. Do this now.

Exercise 11

The debugger has one other useful feature we'll look at today: looking at the stack of function calls.
  1. You can also use the speedbar to actually open files in emacs. Middle-click on the file Fibonacci.java in the speedbar to open it.
  2. Compile this file. What do you see?
  3. Using JDE for development can also help you track down your errors more quickly. While it gives you the same textual output (file, line number), it can do more. Hover your mouse over the first pink line at the top of the compile output in the bottom half of your emacs frame. What does it tell you?
  4. Click on this pink region to go to the problematic line.
  5. It looks as though we made a typo when we were creating our recursive version for calculating Fibonacci numbers. Knowing that the function is actually called calc, fix this problem and recompile.
  6. Now run the program and give it the input 2. What happens?
  7. Let's see if we can use the debugger to figure out what's going on. Add a breakpoint to the first line of the function calc.
  8. Start the debugging process.
  9. The program will start, but actually pause at the first line, we can use the command Jdb ~ Continue to keep running the program until our next breakpoint. Do that.
  10. Use Step Into as many times as you need to forget how many times you've done it.
  11. If you need to get something of a handle on where you are in the program, you can look at the sequence of function calls that have brought you to the current place by looking at the "call stack." In Jdb, you can do this by choosing Jdb ~ Stack ~ Where. Do that now.
  12. You should see that you're several levels deep into the recursive calls. What is the current value of the variable (which in this case is the argument to the function). Are they surprising in any way?
  13. You can navigate the call stack as well so that you may to query variable values in any of the calling functions. This is very useful for testing assumptions you may be making about them. Go up a level in the call stack by choosing Jdb ~ Stack ~ Up from the menu.
  14. Inspect the local variables here. Are any of them problematic?
  15. Keep navigating up the call stack just until you get to a place where the input is not problematic. What is the value of that input and why is the recursive call an issue?
  16. Add the missing test to the recursive procedure and re-run your program (not in debug mode) for several values to ensure that it works correctly.

For those with extra time

If there is still time left, I encourage you to explore some of the other options in JDE and Jdb. Particularly in the debugger. Open some of your previous files (especially those with objects), set some break points and look around. Especially poke a bit at Jdb ~ Display ~ Object.
Created: Jerod Weinman, 8 January 2009
Revised: Jerod Weinman, 14 January 2009
Revised: Jerod Weinman, 18 January 2010
Revised: Jerod Weinman, 17 January 2011
Copyright © 2009-2011 Jerod Weinman.
CC-BY-NC-SA
This work is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License .