Sunday, July 31, 2011

Java 7: Try-With-Resources

The "Try With Resources", also called "Automatic Resource Management" (ARM), statement allows you to declare one or more resources in the try statement. When the statement completes, either successfully or unsuccessfully, all of its resources are closed automatically. You don't need to manually close resources in a finally block anymore, which means you don't have to worry about resource leaks.

Here is a method to make a copy of a file, using the Try-With-Resources statement. There are two resources defined in the try statement, which are automatically closed when the statement completes.

public static void copyFile(String src, String dest) throws IOException  {
  try (BufferedReader in = new BufferedReader(new FileReader(src));
       BufferedWriter out = new BufferedWriter(new FileWriter(dest))){
      String line;
      while((line = in.readLine()) != null) {
          out.write(line);
          out.write('\n');
      }
  }//no need to close resources in a "finally"
}
Here is another example, in which I have created my own resources implementing the AutoCloseable interface:
class ResourceA implements AutoCloseable{
  public void read() throws Exception{
    throw new Exception("ResourceA read exception");
  }
  @Override
  public void close() throws Exception {
    throw new Exception("ResourceA close exception");
  }
}

class ResourceB implements AutoCloseable{
  public void read() throws Exception{
    throw new Exception("ResourceB read exception");
  }
  @Override
  public void close() throws Exception {
    throw new Exception("ResourceB close exception");
  }
}

//a test method
public static void test() throws Exception{
  try (ResourceA a = new ResourceA();
       ResourceB b = new ResourceB()) {
    a.read();
    b.read();
  } catch (Exception e) {
    throw e;
  }
}
When this code is executed, a.read() throws an exception. The two resources are automatically closed, first B and then A (in the reverse order to which they were created). The "read" exception is thrown out of the method, and the two "close" exceptions are "suppressed". You can retrieve these suppressed exceptions by calling the Throwable.getSuppressed method from the exception thrown by the try block. The complete stack trace is shown below:
java.lang.Exception: ResourceA read exception
  at ResourceA.read(Dummy.java:48)
  at Dummy.test(Dummy.java:18)
  at Dummy.main(Dummy.java:38)
  Suppressed: java.lang.Exception: ResourceB close exception
    at ResourceB.close(Dummy.java:63)
    at Dummy.test(Dummy.java:20)
    ... 1 more
  Suppressed: java.lang.Exception: ResourceA close exception
    at ResourceA.close(Dummy.java:52)
    at Dummy.test(Dummy.java:20)
    ... 1 more
Further Reading:
The try-with-resources Statement

Java 7: Precise Rethrow

Previously, rethrowing an exception was treated as throwing the type of the catch parameter. For example, let's say that your try block could throw a ParseException or an IOException. To intercept all exceptions and rethrow them, you would have to catch Exception and declare your method as throwing an Exception. This is "imprecise rethrow", because you are throwing a general Exception type (instead of specific ones) and statements calling your method need to catch this general Exception.

This is illustrated below:

//imprecise rethrow.
//must use "throws Exception"
public static void imprecise() throws Exception{
	try {
		new SimpleDateFormat("yyyyMMdd").parse("foo");
		new FileReader("file.txt").read();
	} catch (Exception e) {
		System.out.println("Caught exception: " + e.getMessage());
		throw e;
	}
}
However, in Java 7, you can be more precise about the exception types being rethrown from a method. If you rethrow an exception from a catch block, you are actually throwing an exception type which:
  • the try block can throw,
  • no previous catch clause handles, and
  • is a subtype of one of the types in the declaration of the catch parameter
This leads to improved checking for rethrown exceptions. You can be more precise about the exceptions being thrown from the method and you can handle them a lot better at the calling site.
//java 7: precise rethrow.
//no longer "throws Exception"
public static void precise() throws ParseException, IOException{
	try {
		new SimpleDateFormat("yyyyMMdd").parse("foo");
		new FileReader("file.txt").read();
	} catch (Exception e) {
		System.out.println("Caught exception: " + e.getMessage());
		throw e;
	}
}

//this example handles ParseException
public static void precise2() throws IOException{
	try {
		new SimpleDateFormat("yyyyMMdd").parse("foo");
		new FileReader("file.txt").read();
	} catch(ParseException e){
	    System.out.println("Parse Exception");
	}catch (Exception e) {
		System.out.println("Caught exception: " + e.getMessage());
		throw e;
	}
}
(Note: Early documentation of this feature, states that you have to use a final modifier on the catch parameter, but this restriction was lifted later on, so is not necessary.)

Further Reading
Rethrowing Exceptions with More Inclusive Type Checking

Saturday, July 30, 2011

Java 7: Safe Varargs Method Invocation

In previous versions of Java, when you invoke a varargs method with a non-reifiable varargs type, the compiler generates a warning on the calling statement. Consider the code:
//varargs method
public static <T> void print(T... a) {
  for (T t : a) {
      System.out.println(t);
  }
}

//calling method
public static void main(String[] args){

  print("Hello", "World"); //this is fine

  print(new Pair<Integer,String>(1,"One"), new Pair<Integer,String>(2,"Two"));
  //WARNING: Type safety : A generic array of Pair<Integer,String>
  //is created for a varargs parameter
}
This because the compiler tries to create an array of Pair<Integer,String>[] to hold the varargs, which is not permitted because Pair<Integer,String> is type erased at runtime to just Pair. (More information here.) To suppress this warning, you need to add @SuppressWarnings("unchecked") to each method which makes a call to the varargs method.

In JDK7, the warning has been moved from the call site to the varargs method declaration and you can annotate the varargs method with @SafeVarargs in order to suppress it. This reduces the total number of warnings reported and those that have to be suppressed.

@SafeVarargs
// WARNING SUPPRESSED: Type safety: Potential heap pollution via varargs parameter a
public static <T> void print(T... a) {
  for (T t : a) {
      System.out.println(t);
  }
}

public static void main(String[] args){
  print("Hello", "World");
  print(new Pair<Integer,String>(1,"One"), new Pair<Integer,String>(2,"Two"));
  //no warnings :)
}
You can see this annotation used in JDK7's Arrays.asList method:

@SafeVarargs
public static <T> List<T> asList(T... a) {
   return new ArrayList<>(a);
}
Eclipse support:
Quick fix gives you the option to Add @SafeVarargs to your method.

Further Reading:
Improved Compiler Warnings and Errors When Using Non-Reifiable Formal Parameters with Varargs Methods

Java 7: Strings in Switch

Strings in switch gives you the ability to switch on string values just like you can currently do on primitives. Previously, you would have had to create chained if-else tests for string equality or introduce an enum, which is not necessary anymore.

The strings-in-switch feature works by first switching on the hashCode of the String and then performing an equals test.

Here is an example of a method which returns the number of days in a month. It uses if-else statements and string equality:
public static int getDaysInMonth(String month, int year) {
    if("January".equals(month) ||
       "March".equals(month)   ||
       "May".equals(month)     ||
       "July".equals(month)    ||
       "August".equals(month)  ||
       "October".equals(month) ||
       "December".equals(month))
        return 31;
    else if("April".equals(month)    ||
            "June".equals(month)     ||
            "September".equals(month)||
            "November".equals(month))
        return 30;
    else if("February".equals(month))
        return ((year % 4 == 0 && year % 100 != 0) ||
                 year % 400 == 0) ? 29 : 28;
    else
        throw new IllegalArgumentException("Invalid month: " + month);
}
The same code can be rewritten neatly using strings-in-switch as follows:
public static int getDaysInMonth2(String month, int year) {
    switch(month) {
        case "January":
        case "March":
        case "May":
        case "July":
        case "August":
        case "October":
        case "December":
            return 31;
        case "April":
        case "June":
        case "September":
        case "November":
            return 30;
        case "February":
            return ((year % 4 == 0 && year % 100 != 0) ||
                     year % 400 == 0) ? 29 : 28;
        default:
            throw new IllegalArgumentException("Invalid month: " + month);
    }
}
Further Reading:
Strings in switch Statements

Java 7: Underscores in Numbers and Binary Literals

In order to aid readability, you can now place underscores between numbers but you must start and end with a digit. For example:
int million = 1_000_000;
float pi = 3.14_159f;
JDK7 also allows you to express integer literals in binary form. This makes it easier to read code which uses bitwise operations. In order to do this, prefix your binary sequence with 0b or 0B. For example:
//previously, you would have had to do it like this:
int x = Integer.parseInt("1000", 2);

//in jdk7, you can create a binary literal like this:
int eight = 0b1000;

//easier to read bitwise operations
int four = 0b1000>>1;
Further Reading:
Underscores in Numeric Literals Binary Literals

Java 7: Multi-catch

You can now catch more than one exception in a single catch clause which removes redundant code.

Here is an example of a statement which throws multiple exceptions:

try {
    Class.forName("Object").newInstance();
} catch (ClassNotFoundException e) {
    e.printStackTrace();
} catch (InstantiationException e) {
    e.printStackTrace();
} catch (IllegalAccessException e) {
    e.printStackTrace();
}
In JDK7, you can collapse the catch blocks into a single one:
try {
    Class.forName("Object").newInstance();
} catch (ClassNotFoundException |
         InstantiationException |
         IllegalAccessException e) {
    e.printStackTrace();
}
Eclipse Support:
  • If you have multiple catch clauses, quick fix gives you the option to Combine catch blocks provided all the catch bodies are the same

  • Conversely, if you have a multi-catch clause, quick fix gives you the option to Use separate catch blocks so that you can handle each exception separately

  • Quick fix gives you the option to Move exception to separate catch block which allows you to take exceptions out of the multi-catch in case you want to handle them separately

  • Quick fix also gives you the option to Surround with try/multi-catch
Further Reading
Handling More Than One Type of Exception

Java 7: Diamond Operator

The diamond operator (<>) removes the need for explicit type arguments in constructor calls to generic classes, thereby reducing visual clutter. For example:
//previously:
Map<Integer, List<String>> map = new HashMap<Integer, List<String>>();

//in jdk7, use the diamond operator. Saves typing!
Map<Integer, List<String>> map2 = new HashMap<>();

List<?> list = new ArrayList<>();
The compiler infers the type on the right side. So if you have a list of ?, the compiler will infer a list of Object.

Eclipse support:

  • Eclipse Content Assist (Ctrl + Space), auto-completes using a diamond instead of explicit type arguments. So, in the example above, when you type new HashM[Ctrl+Space], Eclipse will insert new HashMap<>();.

  • You can also configure Eclipse to warn you if you use explicit type arguments, instead of a diamond. To do this, go to your Preferences and navigate to Java > Compiler > Errors/Warnings. In the Generic types section, select Warning against Redundant type arguments. Eclipse will then offer you a quick-fix to remove the type arguments, if you accidently put them in.
Further Reading:
Type Inference for Generic Instance Creation

Using Java 7 in Eclipse

1. Download Eclipse 3.7 Maintenance Build:
Eclipse 3.7 does not have support for Java 7, but the good news is that you can download a a 3.7 "maintenance build" (>= M20110729-1400) which does. I downloaded mine from here. The download was really slow, because it was coming from Canada and there were no other mirrors!

2. Add a Java 7 JRE:
Start Eclipse and go to Window > Preferences. Navigate to Java > Installed JREs and add your Java 7 JRE to the list, as the default JRE.

3. Upgrade Compiler Compliance Level:
Once again, in your preferences go to Java > Compiler and select 1.7 as the "Compiler compliance level".

4. Check Project JRE:
If you are working on an existing project, you need to make sure that the project is using JDK7 system library. Go into your project properties and into Java Build Path. Select the Libraries tab and check the version of your JRE System Library. If necessary, press Edit... to change it to JDK7.

5. Test it out:
Create a test class and use a Java 7 feature e.g. List<String> list = new ArrayList<>();. This should compile successfully. Eclipse should even be able to auto-complete the diamond.

The latest news on Eclipse Java 7 support can be found on the Eclipse wiki: http://wiki.eclipse.org/JDT/Eclipse_Java_7_Support_(BETA).

Friday, July 29, 2011

Java 7 is here!

I've been looking forward to Java 7 for a long time and it is finally here! This release is jam-packed with new features and I am really excited about trying it out!

There are great additions to the concurrency package such as a fork/join framework, phasers, transfer queues and threadlocal pseudo-random number generators.

Also, as part of Project Coin (JSR 334), JDK7 includes a set of small language changes intended to simplify common, day-to-day programming tasks and reduce boilerplate such as:

  • Strings in switch
  • Binary integral literals and underscores in numeric literals
  • Multi-catch and more precise rethrow
  • Improved Type Inference for Generic Instance Creation (diamond)
  • try-with-resources statement
  • Simplified Varargs Method Invocation
For a full list of changes take a look at the release notes.

I'm going to be writing about the new features in Java 7 as I learn about them, so stay tuned!

Sunday, July 24, 2011

Viewing CSV Files

I find CSV (or, to be more general, DSV) files difficult to read on Unix because you can't tell which column a value is in. So I always end up importing them into a spreadsheet which is a pain. Here is an example of a small pipe-delimited file containing book data:
Title|Author|CoAuthor|Year|ISBN
Carrie|Stephen King||1974|978-0385086950
The Human Web|William McNeill|Robert McNeill|2003|978-0393051797
It would be a lot easier to read, if I could convert the file into dictionaries of key:value pairs in order to see which columns the values were referring to, like this:
Title:Carrie
Author:Stephen King
CoAuthor:
Year:1974
ISBN:978-0385086950

Title:The Human Web
Author:William McNeill
CoAuthor:Robert McNeill
Year:2003
ISBN:978-0393051797
So, I wrote the following Bash script to convert a delimiter separated file into a collection of dictionaries. It uses awk to read the first row, which contains the column names, split it and store it in an array. It then prints out the remaining rows along with their column names which are looked up from the array.
#! /bin/bash
# CSV Viewer
# Usage: csv [-d delim] filename
# default delimiter is pipe.
#
# Input file:
# h1|h2|h3
# v1|v2|v3
# w1|w2|w3
#
# Output:
# h1: v1
# h2: v2
# h3: v3
#
# h1: w1
# h2: w2
# h3: w3

delim=|
while getopts "d:" OPTION
do
   case $OPTION in
     d) delim=$OPTARG; shift $((OPTIND-1)) ;;
   esac
done

if [ $# -eq 0 ]
then
    echo "Usage: csv [-d delim] filename" >&2
    exit 1
fi
awk -F "$delim" '{if(NR==1)split($0,arr);else for(i=1;i<=NF;i++)print arr[i]":"$i;print "";}' "$1"
Running the script:
sharfah@starship:~> csv.sh -d '|' file
Title:Carrie
Author:Stephen King
CoAuthor:
Year:1974
ISBN:978-0385086950

Title:The Human Web
Author:William McNeill
CoAuthor:Robert McNeill
Year:2003
ISBN:978-0393051797

Saturday, July 23, 2011

Copying Eclipse Preferences

If you want to transfer your preferences from one Eclipse installation to another, you can try the following approaches:

Option 1: Export/Import
Export your current preferences to a file and then import them into your new installation.
Go to File > Export and then choose to export General > Preferences to the local filesystem. Then start your second version of Eclipse, go to File > Import and choose to import General > Preferences.

Option 2: Copy runtime setting directory
Copy ${ECLIPSE_WORKSPACE}/.metadata/.plugins/org.eclipse.core.runtime/.settings from the existing installation to the new one.

Sunday, July 17, 2011

Tracing Java Applications with BTrace

BTrace is a dynamic tracing tool for Java. It allows you to insert tracing actions into the classes of a running Java program. This is especially useful, if you are using a third-party library. So, if you want to know whenever a certain method is called in your program, you can tell BTrace to print out a message whenever that method is hit. See the User Guide for more information.

Quick Start:

  • Download BTrace from here
  • Extract the release to a directory e.g. ~/btrace
  • Write a BTrace program. There are many samples present in the samples directory. Here is one of mine: the program below prints a message whenever the target program calls the ArrayList.add() method.
  • import com.sun.btrace.annotations.*;
    import static com.sun.btrace.BTraceUtils.*;
    import java.util.*;
    @BTrace
    public class ArrayListTrace {
    
        // @OnMethod annotation tells where to probe.
        // In this example, we are interested in entry
        // into the ArrayList.add() method.
        @OnMethod(
            clazz="java.util.ArrayList",
            method="add";
        )
        // print out what was added
        public static void alert(@Self ArrayList self, Object o) {
            print("ADDED ");
            println(o);
        }
    }
    
  • Compile your script:
  • javac -cp "~/btrace/build/*" ArrayListTrace.java
    
  • Start the java program you want to probe and get its pid.
  • Run BTrace and watch the messages appear:
  • ~/btrace/bin/btrace -cp ".:~/btrace/build/*" <PID> ArrayListTrace.class
    
Useful BTrace Programs:

Here are a few useful BTrace programs I have used in the past:
  • OnThrow: Prints out the stack trace of an exception whenever a Throwable is created. This way you can capture all exceptions, even those that have been swallowed.
  • LogTracer: Prints out log messages.
  • AllMethods: Prints out the name of every method entered.