Sunday, August 28, 2011

Profiling Perl Code

I've started using NYTProf to profile and optimise my perl code. It produces a very useful report showing how much time is spent in each subroutine and statement.

Usage:

perl -d:NYTProf script.pl
or
perl -d:NYTProf -I/path/to/Devel-NYTProf/4.06/lib/perl5 script.pl
The output of the profiler is written to ./nytprof.out.

Use the following command to create HTML reports from the profiler's results:

/path/Devel-NYTProf/4.06/bin/nytprofhtml --file nytprof.out -out ./htmlReports --delete

Wednesday, August 24, 2011

Play My Code: Chain Reaction

I've just published a new game called Chain Reaction on Play My Code.

Play My Code is a place where you can create your own online games easily using the site's Quby language. The games are compiled into native JavaScript, compatible with all modern HTML5-compliant browsers. Once you've written a game, you can embed it on your website or blog, like I have done below. It's like YouTube, but for games!

Here's Chain Reaction! The aim of the game, is to start a chain reaction (by clicking on the screen) and explode as many atoms as possible. See how many levels you can complete!

Click here to see all my games.

Sunday, August 21, 2011

Java 7: ThreadLocalRandom for Concurrent Random Numbers

The ThreadLocalRandom class in JDK 7, allows you to generate random numbers from multiple threads. It is more efficient than using shared Random objects and will result in better performance as there is less overhead and contention.

In addition, this class also provides "bounded" generation methods.

For example, the statement below generates a random number between 1 (inclusive) and 100 (exclusive).

int random = ThreadLocalRandom.current().nextInt(1,100);
Wait, there's a BUG!
While trying out this class, I noticed that the SAME random numbers were being produced across all my threads. I then discovered this bug which reported the same issue I was having. It appears that the seed is never initialised so the same random numbers are produced every time. I wouldn't recommend using this class until the bug is fixed. The following code illustrates the issue:
//3 threads
for(int i = 0; i < 3; i++) {
    final Thread thread = new Thread() {
        @Override
        public void run() {
            System.out.print(Thread.currentThread().getName() + ":");

            //each thread prints 3 random numbers
            for(int j = 0; j < 3; j++) {
                final int random = ThreadLocalRandom.current().nextInt(1, 50);
                System.out.print(random + ",");
            }
            System.out.println();
        }
    };
    thread.start();
    thread.join();
}
prints:
Thread-0:1,5,24,
Thread-1:1,5,24,
Thread-2:1,5,24,

Saturday, August 20, 2011

LESSOPEN Powers Up Less

A really useful feature of the Unix less pager is LESSOPEN which is the "input preprocessor" for less. This is a script, defined in the LESSOPEN environment variable, which is invoked before the file is opened. It gives you the chance to modify the way the contents of the file are displayed. Why would you want to do this? The most common reason is to uncompress files before you view them, allowing you to less GZ files. But it also allows you to list the contents of zip files and other archives. I like to use it to format XML files and to view Java class files by invoking jad.

You can download a really useful LESSOPEN script from http://sourceforge.net/projects/lesspipe/ and then extend it if necessary.

To use it, simply add export LESSOPEN="|/path/to/bin/lesspipe.sh %s" to your bashrc.

You can then less:

  • directories
  • compressed files
  • archives, to list the files contained in them
  • files contained in archives e.g. less foo.zip:bar.txt
  • binary files

Sunday, August 14, 2011

Useful Eclipse Templates for Faster Coding

I wrote about my Eclipse code templates a few years ago and since then I've made a quite a few changes to them. I've added a few new templates to help with JUnit tests and xml parsing. I've also updated my existing file IO templates to use Java 7 features.

Templates are simply "magic words" or shortcuts to standard blocks of code or text. They are very handy because once you have them setup you don't have to waste time writing boilerplate code any more! An example of a pre-defined template in Eclipse is sysout which expands to System.out.println();. All you have to do is type sysout followed by Ctrl+Space to insert the statement into your Java source file.

To see what templates are defined in Eclipse:

  • Open your Preferences dialog by going to Windows > Preferences
  • On the navigation tree on the left, go to Java > Editor > Templates
  • You will see a list of pre-defined templates
  • You can add new ones by pressing the "New..." button
My templates are shown below. They can also be downloaded from my GitHub repository and then imported into Eclipse.

General Utility Templates:

Nameif
ContextJava statements
Descriptionif null
Pattern
if (${var} == null){
    ${cursor}
}
Nameif
ContextJava statements
Descriptionif not null
Pattern
if (${var} != null){
    ${cursor}
}
Namefor
ContextJava statements
Descriptioniterate over map
Pattern
${:import(java.util.Map.Entry)}
for(Entry<${key:argType(map,0)},${value:argType(map,1)}> entry :
                    ${map:var(java.util.Map)}.entrySet()) {
    ${key} key = entry.getKey();
    ${value} value = entry.getValue();
    ${cursor}
}
Namestrf
ContextJava
Descriptionformat string
Pattern
String.format("${word_selection}${}",${var}${cursor})
Namesysf
ContextJava statements
Descriptionprint formatted string to standard out
Pattern
System.out.printf("${word_selection}${}",${var}${cursor});
Namestatic_final
ContextJava type members
Descriptionstatic final field
Pattern
${visibility:link(
              public,
              protected,
              private)} static final ${type} ${NAME} = ${word_selection}${};

File IO Templates:
The following templates are useful for reading or writing files. They use Java 7 features such as try-with-resources to automatically close files. They also use methods from NIO2.0 to obtain a buffered reader and read the file.

Namereadfile
ContextJava statements
Descriptionread text from file
Pattern
${:import(java.nio.file.Files,
          java.nio.file.Paths,
          java.nio.charset.Charset,
          java.io.IOException,
          java.io.BufferedReader)}
try (BufferedReader in = Files.newBufferedReader(Paths.get(${fileName:var(String)}),
                                                 Charset.forName("UTF-8"))) {
    String line = null;
    while ((line = in.readLine()) != null) {
        ${cursor}
    }
} catch (IOException e) {
    // ${todo}: handle exception
}
Namereadfile
ContextJava statements
Descriptionread all lines from file as a list
Pattern
${:import(java.nio.file.Files,
          java.nio.file.Paths,
          java.nio.charset.Charset,
          java.util.List,
          java.util.ArrayList)}
Lis<String> lines = new ArrayList<>();
try{
	lines = Files.readAllLines(Paths.get(${fileName:var(String)}),
                                        Charset.forName("UTF-8"));
}catch (IOException e) {
    // ${todo}: handle exception
}
${cursor}
Namewritefile
ContextJava statements
Descriptionwrite text to file
Pattern
${:import(java.nio.file.Files,
          java.nio.file.Paths,
          java.nio.Charset,
          java.io.IOException,
          java.io.BufferedWriter)}
try (BufferedWriter out = Files.newBufferedWriter(Paths.get(${fileName:var(String)}),
                                                  Charset.forName("UTF-8"))) {
    out.write(${string:var(String)});
    out.newLine();
    ${cursor}
} catch (IOException e) {
    // ${todo}: handle exception
}

XML Templates:
The following templates are used to read xml files or strings and return a DOM.

Nameparsexml
ContextJava statements
Descriptionparse xml file as Document
Pattern
${:import(org.w3c.dom.Document,
          javax.xml.parsers.DocumentBuilderFactory,
          java.io.File,
          java.io.IOException,
          javax.xml.parsers.ParserConfigurationException,
          org.xml.sax.SAXException)}
Document doc = null;
try {
	doc = DocumentBuilderFactory.newInstance()
			.newDocumentBuilder()
			.parse(new File(${filename:var(String)}));
} catch (SAXException | IOException | ParserConfigurationException e) {
	// ${todo}: handle exception
}
${cursor}
Nameparsexml
ContextJava statements
Descriptionparse xml string as Document
Pattern
${:import(org.w3c.dom.Document,
          javax.xml.parsers.DocumentBuilderFactory,
          org.xml.sax.InputSource,
          java.io.StringReader,
          java.io.IOException,
          javax.xml.parsers.ParserConfigurationException,
          org.xml.sax.SAXException)}
Document doc = null;
try {
	doc = DocumentBuilderFactory.newInstance()
			.newDocumentBuilder()
			.parse(new InputSource(new StringReader(${str:var(String)})));
} catch (SAXException | IOException | ParserConfigurationException e) {
	// ${todo}: handle exception
}
${cursor}

Logging Templates:
The templates below are useful for creating a logger and logging messages. I use SLF4J, but they could easily be tweaked to use any other logging framework.

Namelogger
ContextJava type members
Descriptioncreate new logger
Pattern

${:import(org.slf4j.Logger,
          org.slf4j.LoggerFactory)}
private static final Logger LOGGER =
       LoggerFactory.getLogger(${enclosing_type}.class);
Namelogd
ContextJava statements
Descriptionlogger debug
Pattern
if(LOGGER.isDebugEnabled())
     LOGGER.debug(${word_selection}${});
${cursor}
Namelogi
ContextJava statements
Descriptionlogger info
Pattern
LOGGER.info(${word_selection}${});
${cursor}
Namelogerr
ContextJava statements
Descriptionlogger error
Pattern
LOGGER.error(${word_selection}${}, ${exception_variable_name});
Namelogthrow
ContextJava statements
Descriptionlog error and throw exception
Pattern
LOGGER.error(${word_selection}${}, ${exception_variable_name});
throw ${exception_variable_name};
${cursor}

JUnit Templates:
The templates below assist in writing JUnit tests.

Namebefore
ContextJava type members
Descriptionjunit before method
Pattern
${:import (org.junit.Before)}

@Before
public void setUp() {
    ${cursor}
}
Nameafter
ContextJava type members
Descriptionjunit after method
Pattern
${:import (org.junit.After)}

@After
public void tearDown() {
    ${cursor}
}
Namebeforeclass
ContextJava type members
Descriptionjunit beforeclass method
Pattern
${:import (org.junit.BeforeClass)}

@BeforeClass
public static void oneTimeSetUp() {
    // one-time initialization code
    ${cursor}
}
Nameafterclass
ContextJava type members
Descriptionjunit afterclass method
Pattern
${:import (org.junit.AfterClass)}

@AfterClass
public static void oneTimeTearDown() {
    // one-time cleanup code
    ${cursor}
}

Do YOU have any useful templates? If so, share them in the comments section!

Changing Java Library Path at Runtime

The java.library.path system property instructs the JVM where to search for native libraries. You have to specify it as a JVM argument using -Djava.library.path=/path/to/lib and then when you try to load a library using System.loadLibrary("foo"), the JVM will search the library path for the specified library. If it cannot be found you will get an exception which looks like:
Exception in thread "main" java.lang.UnsatisfiedLinkError: no foo in java.library.path
	at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1734)
	at java.lang.Runtime.loadLibrary0(Runtime.java:823)
	at java.lang.System.loadLibrary(System.java:1028)
The java.library.path is read only once when the JVM starts up. If you change this property using System.setProperty, it won't make any difference.

Here is the code from ClassLoader.loadLibrary which shows how the path is initialised:

if (sys_paths == null) {
    usr_paths = initializePath("java.library.path");
    sys_paths = initializePath("sun.boot.library.path");
}
As you can see from the code above, the usr_paths variable is only initialised if sys_paths is null, which will only be once.

So, how can you modify the library path at runtime? There are a couple of ways to do this, both involving reflection. You should only do this if you really have to.

Option 1: Unset sys_paths
If you set sys_paths to null, the library path will be re-initialised when you try to load a library. The following code does this:

/**
 * Sets the java library path to the specified path
 *
 * @param path the new library path
 * @throws Exception
 */
public static void setLibraryPath(String path) throws Exception {
    System.setProperty("java.library.path", path);

    //set sys_paths to null
    final Field sysPathsField = ClassLoader.class.getDeclaredField("sys_paths");
    sysPathsField.setAccessible(true);
    sysPathsField.set(null, null);
}
Option 2: Add path to usr_paths
Instead of having to re-evaluate the entire java.library.path and sun.boot.library.path as in Option 1, you can instead append your path to the usr_paths array. This is shown in the following code:
/**
* Adds the specified path to the java library path
*
* @param pathToAdd the path to add
* @throws Exception
*/
public static void addLibraryPath(String pathToAdd) throws Exception{
    final Field usrPathsField = ClassLoader.class.getDeclaredField("usr_paths");
    usrPathsField.setAccessible(true);

    //get array of paths
    final String[] paths = (String[])usrPathsField.get(null);

    //check if the path to add is already present
    for(String path : paths) {
        if(path.equals(pathToAdd)) {
            return;
        }
    }

    //add the new path
    final String[] newPaths = Arrays.copyOf(paths, paths.length + 1);
    newPaths[newPaths.length-1] = pathToAdd;
    usrPathsField.set(null, newPaths);
}

Saturday, August 13, 2011

Dotfiles in Git

I've added all my dotfiles (including my entire bash profile and vimrc) to my GitHub dotfiles repository. Whenever I make any changes, I will commit them to the repository.

In order to download the latest version, go to my Downloads page. Alternatively, if you have git installed, use the following command, to clone my repository:

git clone git://github.com/sharfah/dotfiles.git
This will download them to a directory called dotfiles. You can then copy the files recursively (cp -r) to your home directory (don't forget to backup your original files first!). Alternatively, use symlinks.

Sunday, August 07, 2011

Java 7: WatchService for File Change Notification

The Watch Service API in JDK7 allows you to watch a directory for changes to files and receive notification events when a file is added, deleted or modified. You no longer need to poll the file system for changes which is inefficient and doesn't scale well.

The code below shows how you would use the Watch Service API. First, you have to create a WatchService for the file system and then register the directory you want to monitor with it. You have to specify which events (create, modify or delete) you are interested in receiving. Then start an infinite loop to wait for events. When an event occurs, a WatchKey is placed into the watch service's queue and you have to call take to retrieve it. You can then query the key for events and print them out.

/**
 * Watch the specified directory
 * @param dirname the directory to watch
 * @throws IOException
 * @throws InterruptedException
 */
public static void watchDir(String dir)
    throws IOException, InterruptedException{

  //create the watchService
  final WatchService watchService = FileSystems.getDefault().newWatchService();

  //register the directory with the watchService
  //for create, modify and delete events
  final Path path = Paths.get(dir);
  path.register(watchService,
            StandardWatchEventKinds.ENTRY_CREATE,
            StandardWatchEventKinds.ENTRY_MODIFY,
            StandardWatchEventKinds.ENTRY_DELETE);

  //start an infinite loop
  while(true){

    //remove the next watch key
    final WatchKey key = watchService.take();

    //get list of events for the watch key
    for (WatchEvent<?> watchEvent : key.pollEvents()) {

      //get the filename for the event
      final WatchEvent<Path> ev = (WatchEvent<Path>)watchEvent;
      final Path filename = ev.context();

      //get the kind of event (create, modify, delete)
      final Kind<?> kind = watchEvent.kind();

      //print it out
      System.out.println(kind + ": " + filename);
    }

    //reset the key
    boolean valid = key.reset();

    //exit loop if the key is not valid
    //e.g. if the directory was deleted
      if (!valid) {
          break;
      }
  }
}
Demo:
$ java Watcher &
$ touch foo
ENTRY_CREATE: foo
$ echo hello >> foo
ENTRY_MODIFY: foo
$ rm foo
ENTRY_DELETE: foo

Java 7: Working with Zip Files

The Zip File System Provider in JDK7 allows you to treat a zip or jar file as a file system, which means that you can perform operations, such as moving, copying, deleting, renaming etc, just as you would with ordinary files. In previous versions of Java, you would have to use ZipEntry objects and read/write using ZipInputStreams and ZipOutputStreams which was quite messy and verbose. The zip file system makes working with zip files much easier!

This post shows you how to create a zip file and extract/list its contents, all using a zip file system.

Constructing a zip file system:
In order to work with a zip file, you have to construct a "zip file system" first. The method below shows how this is done. You need to pass in a properties map with create=true if you want the file system to create the zip file if it doesn't exist.

/**
 * Returns a zip file system
 * @param zipFilename to construct the file system from
 * @param create true if the zip file should be created
 * @return a zip file system
 * @throws IOException
 */
private static FileSystem createZipFileSystem(String zipFilename,
                                              boolean create)
                                              throws IOException {
  // convert the filename to a URI
  final Path path = Paths.get(zipFilename);
  final URI uri = URI.create("jar:file:" + path.toUri().getPath());

  final Map<String, String> env = new HashMap<>();
  if (create) {
    env.put("create", "true");
  }
  return FileSystems.newFileSystem(uri, env);
}
Once you have a zip file system, you can invoke methods of the java.nio.file.FileSystem, java.nio.file.Path and java.nio.file.Files classes to manipulate the zip file.

Unzipping a Zip File:
In order to extract a zip file, you can walk the zip file tree from the root and copy files to the destination directory. Since you are dealing with a zip file system, extracting a directory is exactly the same as copying a directory recursively to another directory. The code below demonstrates this. (Note the use of the try-with-resources statement to close the zip file system automatically when done.)

/**
 * Unzips the specified zip file to the specified destination directory.
 * Replaces any files in the destination, if they already exist.
 * @param zipFilename the name of the zip file to extract
 * @param destFilename the directory to unzip to
 * @throws IOException
 */
public static void unzip(String zipFilename, String destDirname)
    throws IOException{

  final Path destDir = Paths.get(destDirname);
  //if the destination doesn't exist, create it
  if(Files.notExists(destDir)){
    System.out.println(destDir + " does not exist. Creating...");
    Files.createDirectories(destDir);
  }

  try (FileSystem zipFileSystem = createZipFileSystem(zipFilename, false)){
    final Path root = zipFileSystem.getPath("/");

    //walk the zip file tree and copy files to the destination
    Files.walkFileTree(root, new SimpleFileVisitor<Path>(){
      @Override
      public FileVisitResult visitFile(Path file,
          BasicFileAttributes attrs) throws IOException {
        final Path destFile = Paths.get(destDir.toString(),
                                        file.toString());
        System.out.printf("Extracting file %s to %s\n", file, destFile);
        Files.copy(file, destFile, StandardCopyOption.REPLACE_EXISTING);
        return FileVisitResult.CONTINUE;
      }

      @Override
      public FileVisitResult preVisitDirectory(Path dir,
          BasicFileAttributes attrs) throws IOException {
        final Path dirToCreate = Paths.get(destDir.toString(),
                                           dir.toString());
        if(Files.notExists(dirToCreate)){
          System.out.printf("Creating directory %s\n", dirToCreate);
          Files.createDirectory(dirToCreate);
        }
        return FileVisitResult.CONTINUE;
      }
    });
  }
}
Creating a Zip File:
The following method shows how to create a zip file from a list of files. If a directory is passed in, it walks the directory tree and copies files into the zip file system:
/**
 * Creates/updates a zip file.
 * @param zipFilename the name of the zip to create
 * @param filenames list of filename to add to the zip
 * @throws IOException
 */
public static void create(String zipFilename, String... filenames)
    throws IOException {

  try (FileSystem zipFileSystem = createZipFileSystem(zipFilename, true)) {
    final Path root = zipFileSystem.getPath("/");

    //iterate over the files we need to add
    for (String filename : filenames) {
      final Path src = Paths.get(filename);

      //add a file to the zip file system
      if(!Files.isDirectory(src)){
        final Path dest = zipFileSystem.getPath(root.toString(),
                                                src.toString());
        final Path parent = dest.getParent();
        if(Files.notExists(parent)){
          System.out.printf("Creating directory %s\n", parent);
          Files.createDirectories(parent);
        }
        Files.copy(src, dest, StandardCopyOption.REPLACE_EXISTING);
      }
      else{
        //for directories, walk the file tree
        Files.walkFileTree(src, new SimpleFileVisitor<Path>(){
          @Override
          public FileVisitResult visitFile(Path file,
              BasicFileAttributes attrs) throws IOException {
            final Path dest = zipFileSystem.getPath(root.toString(),
                                                    file.toString());
            Files.copy(file, dest, StandardCopyOption.REPLACE_EXISTING);
            return FileVisitResult.CONTINUE;
          }

          @Override
          public FileVisitResult preVisitDirectory(Path dir,
              BasicFileAttributes attrs) throws IOException {
            final Path dirToCreate = zipFileSystem.getPath(root.toString(),
                                                           dir.toString());
            if(Files.notExists(dirToCreate)){
              System.out.printf("Creating directory %s\n", dirToCreate);
              Files.createDirectories(dirToCreate);
            }
            return FileVisitResult.CONTINUE;
          }
        });
      }
    }
  }
}
Listing the contents of a zip file:
This is the same as extracting a zip file except that instead of copying the files visited, we simply print them out:
/**
 * List the contents of the specified zip file
 * @param filename
 * @throws IOException
 * @throws URISyntaxException
 */
public static void list(String zipFilename) throws IOException{

  System.out.printf("Listing Archive:  %s\n",zipFilename);

  //create the file system
  try (FileSystem zipFileSystem = createZipFileSystem(zipFilename, false)) {

    final Path root = zipFileSystem.getPath("/");

    //walk the file tree and print out the directory and filenames
    Files.walkFileTree(root, new SimpleFileVisitor<Path>(){
      @Override
      public FileVisitResult visitFile(Path file,
          BasicFileAttributes attrs) throws IOException {
        print(file);
        return FileVisitResult.CONTINUE;
      }

      @Override
      public FileVisitResult preVisitDirectory(Path dir,
          BasicFileAttributes attrs) throws IOException {
        print(dir);
        return FileVisitResult.CONTINUE;
      }

      /**
       * prints out details about the specified path
       * such as size and modification time
       * @param file
       * @throws IOException
       */
      private void print(Path file) throws IOException{
        final DateFormat df = new SimpleDateFormat("MM/dd/yyyy-HH:mm:ss");
        final String modTime= df.format(new Date(
                             Files.getLastModifiedTime(file).toMillis()));
        System.out.printf("%d  %s  %s\n",
                          Files.size(file),
                          modTime,
                          file);
      }
    });
  }
}
Further Reading:
Zip File System Provider

Saturday, August 06, 2011

Eclipse: Default to "File Search" Tab in Search Dialog

I don't like the fact that Eclipse defaults to "Java Search" whenever you open the Search Dialog (Ctrl+H), because I almost ALWAYS need "File Search". I then need to press Ctrl+Page Up to switch to the "File Search" tab. The good news is that there is a way to make Eclipse default to "File Search" by changing your key bindings. This is how:
  • Go to Window > Preferences and navigate to General > Keys
  • Type Open Search Dialog in the filter text box to search for the command. You should see it bound to Ctrl+H. Click on the command and press Unbind Command
  • Now type File Search and click on the command. In the Binding text field enter Ctrl+H
  • Press Apply
Now, whenever you hit Ctrl+H, the Search Dialog will show the File Search tab by default!

Another thing...
You can clean up the Search Dialog by removing those tabs that you don't need. Do this by opening the Search Dialog (Ctrl+H) and then clicking on Customize.... Deselect the ones you don't need e.g. Task Search, JavaScript Search, Plug-in Search, Spring Pointcut Matches etc.

My Bash Profile - Part VI: Inputrc

inputrc is the name of the readline startup file. You can set key bindings and certain variables in this file. One of my favourite key bindings is Alt+L to ls -ltrF. I also have bindings which allow you to go back and forth across words using the Ctrl+Left/Right Arrow keys.

To take a look at all your current key bindings execute the command bind -P or bind -p. Check out the man pages for more information.

Update: My dotfiles are now in Git. For the latest version, please visit my GitHub dotfiles repository.

Here is my INPUTRC:

set bell-style none
set completion-ignore-case On
set echo-control-characters Off
set enable-keypad On
set mark-symlinked-directories On
set show-all-if-ambiguous On
set show-all-if-unmodified On
set skip-completed-text On
set visible-stats On

"\M-l": "ls -ltrF\r"
"\M-h": "dirs -v\r"

# If you type any text and press Up/Down,
# you can search your history for commands starting
# with that text
"\e[B": history-search-forward
"\e[A": history-search-backward

# Use Ctrl or Alt Arrow keys to move along words
"\C-[OD" backward-word
"\C-[OC" forward-word
"\e\e[C": forward-word
"\e\e[D": backward-word

"\M-r": forward-search-history
If you have any useful bindings, please share them in the comments section below.

More posts on my Bash profile:

Tuesday, August 02, 2011

Java 7: Deleting a Directory by Walking the File Tree

The Java 7 NIO library allows you to walk a file tree and visit each file in the tree. You do this by implementing a FileVisitor and then calling Files.walkFileTree using the visitor. The visitor has four methods:
  • visitFile: Invoked for a file in a directory.
  • visitFileFailed: Invoked for a file that could not be visited.
  • preVisitDirectory: Invoked for a directory before entries in the directory are visited.
  • postVisitDirectory: Invoked for a directory after entries in the directory, and all of their descendants, have been visited.

Recursively Delete all Files in a Directory:
The following code shows how you can recursively delete a directory by walking the file tree. It does not follow symbolic links. I have overridden the visitFile and postVisitDirectory methods in SimpleFileVisitor so that when a file is visited, it is deleted and after all the files in the directory have been visited, the directory is deleted.

import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import static java.nio.file.FileVisitResult.*;

Path dir = Paths.get("/tmp/foo");
try {
  Files.walkFileTree(dir, new SimpleFileVisitor<Path>() {

      @Override
      public FileVisitResult visitFile(Path file,
              BasicFileAttributes attrs) throws IOException {

          System.out.println("Deleting file: " + file);
          Files.delete(file);
          return CONTINUE;
      }

      @Override
      public FileVisitResult postVisitDirectory(Path dir,
              IOException exc) throws IOException {

          System.out.println("Deleting dir: " + dir);
          if (exc == null) {
              Files.delete(dir);
              return CONTINUE;
          } else {
              throw exc;
          }
      }

  });
} catch (IOException e) {
  e.printStackTrace();
}