Monday, July 27, 2009

Java Developers' Feelings about Java SE 7

The current Java.net poll question is "What is your view of the emerging JDK 7?" As of this blog post, the results are pretty mixed. Just over 40% of the 280 votes are for strongly positive replies of "major step forward" and "important features" while another 40% of respondents have chosen the strongly negative response "most significant problems are not addressed." The rest of the votes are mostly for the lukewarm response "typical JDK release."

In some respects, I am a little surprised that there isn't a higher percentage of dissatisfied respondents. With all of the angst expressed online regarding favorite features excluded from Java SE 7, I expected greater disappointment. It may be that some have resigned themselves to missing a favorite feature or two or it may be that many Java developers feel that the features still planned for Java SE 7 are compelling enough to warrant one of the two more strongly positive results.

The comments on this poll are particularly insightful. These comments seem to validate my own experience and feelings: improved modularity is something to be excited about in Java SE 7, but it would be nice to have a better date/time API and it would be really nice to have reified generics.

In general, I could have voted on a couple of the responses. Although I would have really liked to have seen some of the cut proposed features make it into Java SE 7, I am looking forward to better modularity, null safe operators, improved exception handling, and automatic resource management support. A JVM feature outside of the Java language that I look forward to is the improved support for dynamic languages.

Monday, July 20, 2009

Java SE 7 New Features: Latest News

I recently posted a blog entry on how Groovy provides features that provide a sneak peek at features that might make it into Java SE 7, particularly via Project Coin. It was interesting to see a post from Danny Coward a few days later called Summarizing Java language changes for JDK 7 because I was then able to see which of these features now look like locks for Java SE 7.

Coward mentions in this post that there have not been in Java language changes since the numerous features (Enum Types, Generics, Enhanced for Loop, Annotations, static import, variable number of arguments, and so forth) introduced with J2SE 5.

After mentioning the likely addition of module support and annotations on Java types (JSR 308), Coward moves on to the likely Java SE 7 additions from Project Coin. I have blogged before on Project Coin and its small language changes.

Groovy currently provides support for some of the features that Coward's blog post implies are likely to make it into Java SE 7. These include switching on Strings and null-safe operators. Other features included in Project Coin that are likely to make the cut include Automatic Resource Management (ARM) blocks and more sophisticated exception handling (this feature is available on the JVM via JRuby).

Besides learning new information what is likely to make it into Java SE 7, the post is also interesting because of the reader comments. Clearly, not everyone is happy about what has nearly made it into Java SE 7 or has already missed out on making it into Java SE 7. There is also concern, confusion, and perhaps even a little conspiracy theory speculation regarding what makes it into Java SE 7. I found Joseph Darcy's 2009 JavaOne presentation to be somewhat enlightening on this subject.

Before ending this post, I have two quick sidenotes. First, Darcy's blog post on what earns deprecation in the JDK is interesting. He also points out the reasons for using both @deprecated in Javadoc and @Deprecated in source code. My second side note is that, in honor of today being the 40th anniversary of Armstrong and Aldrin walking on the moon, I recommend watching the under-appreciated movie The Dish.

Monday, July 13, 2009

Using Groovy to See the Future of Java

Besides being a language that can be used for scripting and for writing applications, Groovy also provides the benefit of giving us a taste of new features that might be added to the Java programming language in the future. In this blog post, I will look at some of the features Groovy already supports that may one day be included in the standard Java programming language. Although these features may or may not be implemented exactly the same as they are in Groovy, Groovy's current support of these features allows us to start exploring how we might use such features to improve our development experience.

I have previously blogged about potential new Java features already demonstrable in ActionScript. Many of these same features will be discussed in this blog post, but with Groovy as the language demonstrating the features in current practice. An advantage of using Groovy for this is its closeness to the Java language. In fact, in most of my examples, I will stick very close to traditional Java syntax in order to highlight the potential new feature in Java surroundings. Groovy allows me to demonstrate potential new features of Java while using nearly completely traditional Java alongside those features. Although Groovy often does not require things like semicolons, parentheses, and return statements, I will be using these because they are required in traditional Java.


Safe Navigation Operator

I will start with one of my favorite features of Groovy that I would love to eventually see in the Java programming language. The safe navigation operator checks the object it is operating on for null before trying to access a method or member on that object. I have blogged previously on mechanisms in Java for avoiding NullPointerException and this is one I'd love to add to that list. The following code snippet demonstrates checking for null before accessing an object's method using traditional Java without the ternary operator, using traditional Java with the ternary operator, and using Groovy's safe navigation operator.


/**
* Demonstrates Groovy's safe navigation operator.
*/
public void demonstrateSafeNavigationOperator()
{
final Calendar calendar = null; // this won't be good

//
// traditional Java without ternary operator
//
System.out.print("Null Calendar: ");
if (calendar != null)
{
System.out.println(calendar.get(Calendar.YEAR));
}
else
{
System.out.println("null");
}

//
// traditional Java with ternary operator
//
System.out.println(
"Null Calendar: " + (calendar != null ? calendar.get(Calendar.YEAR) : "null"));

//
// Groovy's safe navigation operator
//
System.out.println("Null Calendar: " + calendar?.get(Calendar.YEAR));
}


I like the safe navigation operator because it's subtle, because it does not preclude any existing Java operator, and it allows the dot operator to still be used in cases when null checking is not desired. This is the operator I would most like to see added to Java.


Elvis Operator

The name alone makes this operator worth watching. The Elvis operator is a shortened version of the ternary operator which essentially says to use the initially provided value if it is non-null and not false or else use a default provided value. The following code snippet shows it in action.


/**
* Demonstrates Groovy's Elvis operator.
*/
public void demonstrateElvisOperator()
{
final String originalText = null;

//
// traditional Java without ternarary operator
//
String newTextString;
if (originalText != null)
{
newTextString = originalText;
}
else
{
newTextString = "Not Provided";
}
System.out.println("Text: " + newTextString);

//
// traditional Java with ternary operator
//
final String newTernaryTextString =
originalText != null ? originalText : "Not Provided";
System.out.println("Text: " + newTernaryTextString);

//
// Groovy's Elvis operator
//
final String newGroovyTextString = originalText ?: "Not Provided";
System.out.println("Text: " + newGroovyTextString);
}


The code above shows traditional Java without ternary, traditional Java with ternary, and the Groovy Elvis operator. The Elvis operator makes the ternary operator even more concise. Like the safe navigation operator, this can be handy in reducing encounters with NullPointerException or the ungainly code needed to avoid such encounters. I don't miss this one in traditional Java as much as I miss the safe navigation operator, however, because the Java ternary operator is available.


Switch on Strings

I blogged specifically on ActionScript allowing switching on Strings. Groovy supports this as well. The following code snippet demonstrates Groovy code switching on Strings after first showing how this is accomplished in traditional Java (with if-else if statements).


/**
* Demonstrate Groovy's ability to switch on Strings.
*/
public void demonstrateSwitchOnString()
{
final String selectedMXBean = THREAD_MXBEAN_NAME;

//
// traditional Java approach (cannot switch on String)
//

// using static imports so that ManagementFactory scoping not necessary
System.out.print("Selected MXBean: ");
if (CLASS_LOADING_MXBEAN_NAME.equals(selectedMXBean))
{
System.out.println("Class Loading");
}
else if (COMPILATION_MXBEAN_NAME.equals(selectedMXBean))
{
System.out.println("Compilation");
}
else if (GARBAGE_COLLECTOR_MXBEAN_DOMAIN_TYPE.equals(selectedMXBean))
{
System.out.println("Garbage Collection");
}
else if (MEMORY_MANAGER_MXBEAN_DOMAIN_TYPE.equals(selectedMXBean))
{
System.out.println("Memory Manager");
}
else if (MEMORY_MXBEAN_NAME.equals(selectedMXBean))
{
System.out.println("Memory");
}
else if (MEMORY_POOL_MXBEAN_DOMAIN_TYPE.equals(selectedMXBean))
{
System.out.println("Memory Pool");
}
else if (OPERATING_SYSTEM_MXBEAN_NAME.equals(selectedMXBean))
{
System.out.println("Operating System");
}
else if (RUNTIME_MXBEAN_NAME.equals(selectedMXBean))
{
System.out.println("Runtime");
}
else if (THREAD_MXBEAN_NAME.equals(selectedMXBean))
{
System.out.println("Threading");
}
else
{
System.out.println(
"Not expecting the type of MXBean you provided: " + selectedMXBean);
}

//
// Groovy approach (go ahead and switch on the strings)
//

// leveraging Groovy's support of static imports here as well
System.out.print("Selected MXBean: ");
switch (selectedMXBean)
{
case CLASS_LOADING_MXBEAN_NAME :
System.out.println("Class Loading");
break;
case COMPILATION_MXBEAN_NAME :
System.out.println("Compilation");
break;
case GARBAGE_COLLECTOR_MXBEAN_DOMAIN_TYPE :
System.out.println("Garbage Collection");
break;
case MEMORY_MANAGER_MXBEAN_DOMAIN_TYPE :
System.out.println("Memory Manager");
break;
case MEMORY_MXBEAN_NAME :
System.out.println("Memory");
break;
case MEMORY_POOL_MXBEAN_DOMAIN_TYPE :
System.out.println("Memory Pool");
break;
case OPERATING_SYSTEM_MXBEAN_NAME :
System.out.println("Operating System");
break;
case RUNTIME_MXBEAN_NAME :
System.out.println("Runtime");
break;
case THREAD_MXBEAN_NAME :
System.out.println("Threading");
break;
default :
System.out.println(
"Not expecting the type of MXBean you provided: " + selectedMXBean);
}
}


With the introduction of enums in J2SE 5, switching on Strings has been less important to me. However, I still run into situations when it would be nice. For those who don't like the switch, Groovy will, of course, support the traditional if-else if structure shown above. In fact, all of the examples in this blog post are being run in Groovy, including the "traditional Java" examples. The above example took advantage of static imports and illustrates the convenience of fabulous J2SE 5 new features support in Groovy.


Multiline Strings

Over the many years that I have developed Java code, one of the little but frequent complaints I hear is about Java's handling of multiline Strings. Groovy supports multiline Strings with its heredoc feature. One can use either three single quotes on the beginning and end of a multiline String or can use three double quotes at the beginning and end to do the same thing with the main difference being whether one wants support for GString expansion (be careful when Googling that term!).

The following code demonstrates the multiline String support in Groovy.


/**
* Demonstrate Groovy's support for multiline Strings (Heredoc).
*/
public void demonstrateMultiLineStrings()
{
//
// Groovy support for multiline Strings (Heredocs).
//
final multiLineGroovyString =
"""This is a very long String that seems to have no end and, in fact,
needs to live over more than one line in my favorite editor.""";
System.out.println("Groovy Heredoc String: " + multiLineGroovyString);
}



GString Expansion

In many of my favorite languages and frameworks, there is an ability to represent a value more significant than the text itself within a String and have that value expanded to that more significant thing when the String is expanded. Groovy supports this concept with GString expansion that uses a syntax very similar to that used for similar purposes in Ant, the Spring Framework, JSP expression language, OpenLaszlo, and Flex.

The code snippet that follows shows this expansion in action and compares it to Java's standard approach of adding such significant values via the + operator. For completeness, I have also included the ability to use varargs and java.io.Console to more nimbly include these more sophisticated values within a single String.


/**
* Demonstrate Groovy's support GStrings.
*/
public void demonstrateGStrings()
{
final Calendar today = Calendar.getInstance();

//
// traditional Java approach available since the beginning
//
System.out.println(
"Today's date is " + today.get(Calendar.DATE) + " "
+ today.getDisplayName(Calendar.MONTH, Calendar.LONG, Locale.US) + " "
+ today.get(Calendar.YEAR));

//
// traditional Java approach available since 1.5 introduction of varargs
// (and using Java SE 6's Console in this case).
//
System.console().printf(
"Today's date is %d %s %s%n",
today.get(Calendar.DATE),
today.getDisplayName(Calendar.MONTH, Calendar.LONG, Locale.US),
today.get(Calendar.YEAR));

//
// The groovy approach
//
System.out.println(
"Today's date is ${today.get(Calendar.DATE)} ${today.getDisplayName(Calendar.MONTH, Calendar.LONG, Locale.US)} ${today.get(Calendar.YEAR)}");
}


The advantage to the Groovy approach is that values to be evaluated can be embedded directly within the String with no need for + operators. It's a small but convenient feature.


BigDecimal Arithmetic

It is common for developers to shy away from the BigDecimal or at least groan about its use because of lack of operators such as +, -, *, and / for BigDecimal (methods with corresponding names must be called on the objects instead).

The code below demonstrates why a developer might choose to use BigDecimal. Note that this is the one code listing in this post that is truly traditional Java rather than Groovy. I include it here to demonstrate the benefit of using BigDecimal in Java.


import java.math.BigDecimal;

/**
* Simple demonstration of how BigDecimal improves precision of arithmetic
* operations.
*/
public class JavaBigDecimalExample
{
/**
* Demonstrate addition imprecision with Java doubles.
*/
public static void demonstrateDoubleAddition()
{
System.out.println("DOUBLE ADDITION");
final double augend = 99.99;
final double addend = 1.99;
final double summary = augend + addend;
System.out.println("SUM: " + summary);
}

/**
* Demonstrate better addition precision with Java BigDecimal.
*/
public static void demonstrateBigDecimalAddition()
{
System.out.println("BIGDECIMAL ADDITION");
final BigDecimal bigDecimalAugend = new BigDecimal("99.99");
final BigDecimal bigDecimalAddend = new BigDecimal("1.99");
final BigDecimal bigDecimalSum = bigDecimalAugend.add(bigDecimalAddend);
System.out.println("SUM: " + bigDecimalSum);
}

/**
* Main function for comparing arithmetic with doubles to arithmetic with
* BigDecimal.
*
* @param arguments Command-line arguments: none expected.
*/
public static void main(final String[] arguments)
{
demonstrateDoubleAddition();
demonstrateBigDecimalAddition();
}
}


When the above simple application is executed, the output looks like that shown in the next screen snapshot.


This example demonstrates the precision problems of floating point arithmetic that are avoided in traditional Java by use of BigDecimal. The next code example compares similar code to that just shown to Groovy's support for operators such as + with the BigDecimal. This certainly makes it a little easier to use and read the operations being performed on the instances of BigDecimal. It also illustrates Groovy's general support for operator overloading.


/**
* Demonstrate BigDecimal arithmetic and show that even doubles arithmetic
* in Groovy is really done with BigDecimal and that Groovy operator
* overloading is supported in Groovy.
*/
public void demonstrateBigDecimalArithmetic()
{
//
// traditional Java approach using double
// (note that Groovy treats double as BigDecimal anyway)
//
final double augend = 99.99;
final double addend = 1.99;
final double summary = augend + addend;
System.out.println("SUM (doubles): " + summary);

//
// traditional Java approach using BigDecimal
//
final BigDecimal bigDecimalAugend = new BigDecimal("99.99");
final BigDecimal bigDecimalAddend = new BigDecimal("1.99");
final BigDecimal bigDecimalSum = bigDecimalAugend.add(bigDecimalAddend);
System.out.println("SUM (BigDecmial.add): " + bigDecimalSum);

//
// Groovier BigDecimal addition (operator overloading!)
//
final BigDecimal bigDecimalSum2 = bigDecimalAugend + bigDecimalAddend;
System.out.println("SUM (BigDecimal+): " + bigDecimalSum2);
}


The output for this code is shown next. Note that the + operator worked just as well as the add method in Groovy.




Properties

A significant portion of the Java development community really wants first-class property support in Java. It's not such a big deal to me, but it is worth discussing here because Groovy provides another good example in this case. The following class is a "pure Groovy" class with all the required code listed.

example.Person.groovy

package example;

class Person
{
/**
* Groovy doesn't require the private modifier for a class's attribute to
* be treated as private.
*/
String name;

/**
* Groovy doesn't require the public modifier for a class's method to be
* treated as public.
*/
String toString() {return "Person's name is " + name;}
}


There are no "get" or "set" methods for the "name" attribute of the "Person" class, but we don't need these where we're going. The next code is some code that sets and gets the "name" of instances of Person.


/**
* Demonstrate Groovy properties.
*/
public void demonstrateProperties()
{
Person person = new Person();
person.name = "Dustin";
System.out.println(Person.getDeclaredField("name"));
System.out.println(person.name);
System.out.println(Person.getDeclaredMethod("toString"));
System.out.println(person.toString());

Person person2 = new Person();
person.setName("Samuel");
System.out.println(person.getName());
}


This code works even though get/set methods were never defined in the Person class. This is because Groovy automatically generates these methods. That is why calling them above works. Groovy property support goes even beyond automatic generation of get/set methods and allows direct access on the properties with the dot (.) operator rather than using get/set. The output shown next demonstrates Groovy's property support in action and proves that the attibute "name" was indeed private, even though it appears directly accessible with the dot operator.




Complete JavaFuturePeek.groovy Script

I have shown snippets of Groovy code throughout this post. For completeness, they are all shown together here in the script JavaFuturePeek.groovy. Note that the example/Person.groovy Groovy class and the JavaBigDecimalExample.java Java class are distinct classes not included in this overall script.

JavaFuturePeek.groovy

import example.Person;
import static java.lang.management.ManagementFactory.*;

/**
* Java-ish class written to demonstrate how Groovy features could provide a
* peek into the future of Java.
*/
public class JavaFuturePeek
{
/**
* Demonstrates Groovy's safe navigation operator.
*/
public void demonstrateSafeNavigationOperator()
{
final Calendar calendar = null; // this won't be good

//
// traditional Java without ternary operator
//
System.out.print("Null Calendar: ");
if (calendar != null)
{
System.out.println(calendar.get(Calendar.YEAR));
}
else
{
System.out.println("null");
}

//
// traditional Java with ternary operator
//
System.out.println(
"Null Calendar: " + (calendar != null ? calendar.get(Calendar.YEAR) : "null"));

//
// Groovy's safe navigation operator
//
System.out.println("Null Calendar: " + calendar?.get(Calendar.YEAR));
}

/**
* Demonstrates Groovy's Elvis operator.
*/
public void demonstrateElvisOperator()
{
final String originalText = null;

//
// traditional Java without ternarary operator
//
String newTextString;
if (originalText != null)
{
newTextString = originalText;
}
else
{
newTextString = "Not Provided";
}
System.out.println("Text: " + newTextString);

//
// traditional Java with ternary operator
//
final String newTernaryTextString =
originalText != null ? originalText : "Not Provided";
System.out.println("Text: " + newTernaryTextString);

//
// Groovy's Elvis operator
//
final String newGroovyTextString = originalText ?: "Not Provided";
System.out.println("Text: " + newGroovyTextString);
}

/**
* Demonstrate Groovy's ability to switch on Strings.
*/
public void demonstrateSwitchOnString()
{
final String selectedMXBean = THREAD_MXBEAN_NAME;

//
// traditional Java approach (cannot switch on String)
//

// using static imports so that ManagementFactory scoping not necessary
System.out.print("Selected MXBean: ");
if (CLASS_LOADING_MXBEAN_NAME.equals(selectedMXBean))
{
System.out.println("Class Loading");
}
else if (COMPILATION_MXBEAN_NAME.equals(selectedMXBean))
{
System.out.println("Compilation");
}
else if (GARBAGE_COLLECTOR_MXBEAN_DOMAIN_TYPE.equals(selectedMXBean))
{
System.out.println("Garbage Collection");
}
else if (MEMORY_MANAGER_MXBEAN_DOMAIN_TYPE.equals(selectedMXBean))
{
System.out.println("Memory Manager");
}
else if (MEMORY_MXBEAN_NAME.equals(selectedMXBean))
{
System.out.println("Memory");
}
else if (MEMORY_POOL_MXBEAN_DOMAIN_TYPE.equals(selectedMXBean))
{
System.out.println("Memory Pool");
}
else if (OPERATING_SYSTEM_MXBEAN_NAME.equals(selectedMXBean))
{
System.out.println("Operating System");
}
else if (RUNTIME_MXBEAN_NAME.equals(selectedMXBean))
{
System.out.println("Runtime");
}
else if (THREAD_MXBEAN_NAME.equals(selectedMXBean))
{
System.out.println("Threading");
}
else
{
System.out.println(
"Not expecting the type of MXBean you provided: " + selectedMXBean);
}

//
// Groovy approach (go ahead and switch on the strings)
//

// leveraging Groovy's support of static imports here as well
System.out.print("Selected MXBean: ");
switch (selectedMXBean)
{
case CLASS_LOADING_MXBEAN_NAME :
System.out.println("Class Loading");
break;
case COMPILATION_MXBEAN_NAME :
System.out.println("Compilation");
break;
case GARBAGE_COLLECTOR_MXBEAN_DOMAIN_TYPE :
System.out.println("Garbage Collection");
break;
case MEMORY_MANAGER_MXBEAN_DOMAIN_TYPE :
System.out.println("Memory Manager");
break;
case MEMORY_MXBEAN_NAME :
System.out.println("Memory");
break;
case MEMORY_POOL_MXBEAN_DOMAIN_TYPE :
System.out.println("Memory Pool");
break;
case OPERATING_SYSTEM_MXBEAN_NAME :
System.out.println("Operating System");
break;
case RUNTIME_MXBEAN_NAME :
System.out.println("Runtime");
break;
case THREAD_MXBEAN_NAME :
System.out.println("Threading");
break;
default :
System.out.println(
"Not expecting the type of MXBean you provided: " + selectedMXBean);
}
}

/**
* Demonstrate Groovy's support for multiline Strings (Heredoc).
*/
public void demonstrateMultiLineStrings()
{
//
// Groovy support for multiline Strings (Heredocs).
//
final multiLineGroovyString =
"""This is a very long String that seems to have no end and, in fact,
needs to live over more than one line in my favorite editor.""";
System.out.println("Groovy Heredoc String: " + multiLineGroovyString);
}

/**
* Demonstrate Groovy's support GStrings.
*/
public void demonstrateGStrings()
{
final Calendar today = Calendar.getInstance();

//
// traditional Java approach available since the beginning
//
System.out.println(
"Today's date is " + today.get(Calendar.DATE) + " "
+ today.getDisplayName(Calendar.MONTH, Calendar.LONG, Locale.US) + " "
+ today.get(Calendar.YEAR));

//
// traditional Java approach available since 1.5 introduction of varargs
// (and using Java SE 6's Console in this case).
//
System.console().printf(
"Today's date is %d %s %s%n",
today.get(Calendar.DATE),
today.getDisplayName(Calendar.MONTH, Calendar.LONG, Locale.US),
today.get(Calendar.YEAR));

//
// The groovy approach
//
System.out.println(
"Today's date is ${today.get(Calendar.DATE)} ${today.getDisplayName(Calendar.MONTH, Calendar.LONG, Locale.US)} ${today.get(Calendar.YEAR)}");
}

/**
* Demonstrate BigDecimal arithmetic and show that even doubles arithmetic
* in Groovy is really done with BigDecimal and that Groovy operator
* overloading is supported in Groovy.
*/
public void demonstrateBigDecimalArithmetic()
{
//
// traditional Java approach using double
// (note that Groovy treats double as BigDecimal anyway)
//
final double augend = 99.99;
final double addend = 1.99;
final double summary = augend + addend;
System.out.println("SUM (doubles): " + summary);

//
// traditional Java approach using BigDecimal
//
final BigDecimal bigDecimalAugend = new BigDecimal("99.99");
final BigDecimal bigDecimalAddend = new BigDecimal("1.99");
final BigDecimal bigDecimalSum = bigDecimalAugend.add(bigDecimalAddend);
System.out.println("SUM (BigDecmial.add): " + bigDecimalSum);

//
// Groovier BigDecimal addition (operator overloading!)
//
final BigDecimal bigDecimalSum2 = bigDecimalAugend + bigDecimalAddend;
System.out.println("SUM (BigDecimal+): " + bigDecimalSum2);
}

/**
* Demonstrate Groovy properties.
*/
public void demonstrateProperties()
{
Person person = new Person();
person.name = "Dustin";
System.out.println(Person.getDeclaredField("name"));
System.out.println(person.name);
System.out.println(Person.getDeclaredMethod("toString"));
System.out.println(person.toString());

Person person2 = new Person();
person.setName("Samuel");
System.out.println(person.getName());
}

/**
* Main function that is run when the command "groovy JavaFuturePeek" is
* executed at the command-line.
*/
public static void main(final String[] arguments)
{
final JavaFuturePeek me = new JavaFuturePeek();
me.demonstrateSafeNavigationOperator();
printSeparatorLine();
me.demonstrateElvisOperator();
printSeparatorLine();
me.demonstrateSwitchOnString();
printSeparatorLine();
me.demonstrateMultiLineStrings();
printSeparatorLine();
me.demonstrateGStrings();
printSeparatorLine();
me.demonstrateBigDecimalArithmetic();
printSeparatorLine();
me.demonstrateProperties();
}

/**
* Print blank line to standard output.
*/
public static void printSeparatorLine()
{
System.out.println(System.getProperty("line.separator"));
}
}


Much more could have been done to make this script "groovier," but I intentionally wanted it to be close to traditional Java to allow the focus to be on what new features in Java might be like.


Script Output

The overall output of the script is not all that exciting, but is shown next.




Conclusion

Groovy provides an excellent playground for trying out features that may be coming to future versions of the Java programming language. Its close relationship to Java makes it even more attractive for this than other less Java-like languages with the same features. In this blog posting, I have attempted to demonstrate Groovy features that may end up in a future version of Java. These proposed new Java features include property support, BigDecimal operators, switch on String, multiline Strings, and the Elvis operator. Other than the brief mention of BigDecimal operator overloading, I did not focus on Groovy's operator overloading here for the same reason I did not mention Groovy's closure support here: they both deserve blog posts of their own. I instead focused on smaller new features here that might someday be added to traditional Java.

Monday, July 6, 2009

2009 JavaOne: VisualVM

VisualVM

I have been excited about the inclusion of VisualVM with Sun's HotSpot since its bundling with Java SE 6 Update 7. VisualVM combines the best of several other Sun-provided Java tools such as the visual tool JConsole and command line tools such as jinfo, jmap, jstat, and jstack. VisualVM can also be downloaded separately from Sun's Java SE 6 implementation from https://visualvm.dev.java.net/download.html.


VisualVM at 2009 JavaOne

I have spoken with many experienced Java developers who have been unaware of the existence of VisualVM. I also found it interesting that in the recent VisualVM blogging contest, VisualVM was described as "the best kept secret" in Java development. Besides holding the blogging contest related to VisualVM, other measures have been taken to make sure that the secret is out. In this blog post, I will focus on two presentations from 2009 JavaOne that go a long way toward getting the word out about the existence and benefits of VisualVM: "Monitoring and Troubleshooting Java Platform Applications with JDK Software" (BOF-4724) and "Hop on Board the Java Troubleshooting Platform" (TS-4247).


Monitoring and Troubleshooting Java Platform Applications with JDK Software

The Birds of a Feather session "Monitoring and Troubleshooting Java Platform Applications with JDK Software" was led by Mandy Chung and Tomas Hurka. Each of these Sun employees possesses the credentials to conduct such a BOF session.

Mandy Chung has worked with JConsole and various Java management related APIs. Her blog post Java SE 6 Monitoring, Management, Diagnosability may be the best online starting point for learning about Java SE 6 management, monitoring, and diagnostics. That particular blog post lists Java SE 6's many features and tools with a concise description of each and links to additional resources on that feature. Chung is also the author of Monitoring and Managing Java SE 6 Platform Applications and a contributor to the Troubleshooting Guide for Java SE 6 with HotSpotVM.

Tomas Hurka presented a BOF at 2008 JavaOne that introduced VisualVM and was called "VisualVM: Integrated and Extensible Troubleshooting Tool for the Java Platform" (BOF-5223). Perhaps most importantly in terms of credentials, Hurka is the lead developer on the VisualVM project.

The BOF presentation only has 17 slides (probably due to demonstrations and discussion), but these are 17 content-packed slides. One of my favorite slides in this presentation is the third slide of the presentation. It is called "Monitoring and Troubleshooting Tools" and contains a table that maps a management/monitoring/troubleshooting feature to a Sun-provided command-line (CLI) tool and to the relevant graphical (GUI) tool. Many articles and blog posts and even the VisualVM home page talk about VisualVM being a composite of the various command-line tools. The table of this slide does the best job I have seen of tying command-line tools to VisualVM and associating VisualVM with the specific troubleshooting feature provided by the command-line tool.

The majority of the presentation focuses on providing additional details and usage information regarding the command line tools and graphical tools mapped on the slide just mentioned. In particular, focus is placed on JConsole, VisualVM, diagnosing deadlocks, diagnosing memory leaks, diagnosing hot lock contention, diagnosing OutOfMemoryError, diagnosing a hung process on Linux or Solaris (Windows support planned), and diagnosing a few other negative conditions.



Hop on Board the Java Troubleshooting Platform

A Sun employee and member of the NetBeans Team, Geertjan Wielenga focuses in this presentation specifically on VisualVM. Wielenga may be best known to many developers for his DZone/JavaLobby articles on NetBeans and VisualVM. The presentation can be roughly described as made up of two major pieces. The first half is devoted to introductory and overview information on using VisualVM and the second half is dedicated to extending VisualVM.

These slides provide a useful introduction to VisualVM, what it is, and why and how one might use it. The slides also show how and why VisualVM can be extended. Two of my favorite slides in this presentation appear toward the end. The slide called "The Future" focuses on potential improvements to VisualVM such as OSGi support and the possibility of more plug-ins for VisualVM. The "References" slide provides links to several useful resources on VisualVM. There is a relatively large amount of demonstration code included with the slides that helps understand lower level details.


Conclusion

The two presentations briefly reviewed here contribute to getting the word out about VisualVM. I have blogged on VisualVM several times and cannot say enough good things about the tool.


Additional Resources

VisualVM Project Page

JavaLobby VisualVM Tagged Articles

The Best Kept Secret in the JDK: VisualVM

VisualVM: Free and Open Source Java Troubleshooter

Java VisualVM Tech Notes

Thread Analysis with VisualVM

Heap Dump and Analysis with VisualVM

Acquiring JVM Runtime Information

VisualVM: jinfo and So Much More

From JConsole to VisualVM

Saturday, July 4, 2009

2009 JavaOne: Groovy/JRuby

The 2009 JavaOne Conference included multiple opportunities to learn about and discuss Groovy. Bill Gloff provides a nice summary of the Groovy-related activities and mentions that Groovy won this year's edition of the Script Bowl. In this blog posting, I will be focusing on two Groovy-related presentations presented at 2009 JavaOne: What's New in Groovy 1.6? (TS-4215) and Comparing Groovy and JRuby (TS-4955).


What's New in Groovy 1.6?

In late 2008, SpringSource acquired G2One, bringing key Groovy developers such as Graeme Rocher and Guillaume Laforge into SpringSource. The latter, Guillaume Laforge, presented Groovy at the aforementioned Script Bowl and was the presenter of "What's New in Groovy 1.6?"

Laforge's presentation was not entirely new to me because I had previously read his article What's New in Groovy 1.6. He mentions in his presentation slides that the examples in the presentation come from the article and suggests reading the article for more detailed coverage of the topics covered in the presentation.

Groovy Overview

In his presentation, Laforge mentions some of the advantages of Groovy that I have significantly appreciated as I have worked with Groovy. I especially like Groovy because it is so easy to apply my years of Java development experience and to mix Java and Groovy; Laforge refers to this benefit as a "flat learning curve" coming from Java. I also like how Laforge refers to Groovy as having a "relaxed grammar derived from the Java 5 grammar."

The "Features at a Glance" slide is a single-slide overview of a subset of nice Groovy features such as Groovy's seamless integration with Java, Groovy's full object-orientation, and Groovy's support of operator overloading.

As part of the introduction to Groovy, the presentation uses the now-common approach of showing a simple Java program that runs as-is in Groovy and then as a much slimmer version that takes advantage of Groovy-specific features. This is the same approach I took in my blog posting Groovy: JVM-based Scripting with Less Ceremony. The ability to write Groovy scripts and applications with anywhere from largely 100% pure traditional Java to almost 100% pure Groovy features is one of the features of Groovy that I find most compelling.

This presentation also introduces the Groovy Web Console. Although I had been aware of this online tool for interactively trying out Groovy, I had never actually used it or even seen it because I had started learning and using Groovy using Groovy from the command line. I tried it out after seeing it in this presentation. Although it is not very difficult to use Groovy from the command line, the web console makes it particularly easy to start using Groovy. For example, I can write a variation of the now-famous one-line Groovy Hello World application and execute it easily within the Groovy Web Console as shown in the next screen snapshot.



As the image above demonstrates, a single line of Groovy can achieve the simple Hello World program that takes several lines in traditional Java.


Performance and Syntactic Improvements

One slide in the presentation focus on performance improvements from Groovy 1.5 to 1.6. According to the presenter, Groovy is now among the fastest of the JVM language implementations. There are a few syntax improvements discussed as well with my favorite being complete support of J2SE 5 features such as enums, annotations, and generics. The presentation points out that Groovy's support for annotations allows it to be used with annotation-driven frameworks and libraries such as Guice.


Groovy Metadata: Abstract Syntax Tree (AST) Transformations

A few slides are devoted to coverage of Groovy 1.6's support for AST Transformations that allow the creation of custom language syntax. Laforge focuses on @Singleton, @Immutable, @Lazy, and @Delegate in this presentation.


Groovy and JSR 223

One of the most exciting features I have enjoyed with Groovy 1.6 is its bundling of a built-in JSR 223-compliant script engine. In fact, I like this so much that I have previously blogged about it. This new feature makes using Groovy within Java code via JSR 223 almost as easy as using the Rhino JavaScript engine that comes with the HotSpot JVM.


Groovy and Java Management Extensions

As proven by the fact that I currently have 43 blog posts tagged as JMX, I really like to read about, write about, and use JMX. It is easy to use any Java APIs and libraries with Groovy, but Groovy 1.6 takes JMX ease of use a step further with the JMX Builder. This presentation devotes a couple of slides to JMX Builder. One slides outlines its main features and the other provides code snippets for each feature. It is a testament to the simplicity of JMX Builder syntax that all of this can be fit onto two slides! I have blogged previously on JMX Builder.


Groovy and OSGi

The last new topic in this presentation is Groovy's "OSGi readiness." OSGi has been a popular topic in recent years and SpringSource has been an early adopter of OSGi, so Groovy's support of it is not surprising.


Summary: What's New in Groovy 1.6?

As stated in his presentation and stated previously in this blog posting, most of the material presented in the presentation is available with different level of detail in the article What's New in Groovy 1.6. If you are interested in Groovy and have not read either, you might want to start with the presentation for a high-level overview and then go to the article for more details.



Comparing Groovy and JRuby

If you are a fan of the original Star Trek series, you will love the slides in this presentation. If you are not a fan of the original Star Trek series but want to learn more about how Groovy compares to JRuby, you will still find most of the slides informative and useful. There are many images from the original Star Trek series interspersed with the technical content of the presentation. I found these images to be not distracting and expect them to generally appeal to the technical crowd without any risk of being offensive as some slides have been recently deemed in at least two recent conferences (Ruby and Flash conferences).

I have been using both Groovy and JRuby in recent months and so was interested to read this presentation and see how Neal Ford's conclusions and observations aligned with mine. In general, he observed many of the similarities and differences I have observed and called out some that I realized were different but had not previously thought about.

I particularly like an early slide in his presentation where he presents an image of a scale with Groovy on the left side and JRuby on the right side and has a single sentence for each. I think these sentences succinctly describe the most important difference (to me) between these dynamic languages: their intent. Ford states that "Groovy dynamicizes the Java platform" while "JRuby brings Ruby to the Java platform." When I have been asked by colleagues about the main difference between the two languages, I have answered this same way, albeit not as elegantly as Ford does.

I have stated that I believe that Groovy appeals most to experienced Java developers who wish to leverage their skills and knowledge in Java and generally are happy with Java, but want to take advantage of some dynamic features, some newer language features (some of which may end up in Java SE 7), and of general script-friendly language attributes. On the other hand, I believe JRuby is more attractive to those developers who either are more comfortable with Ruby or wish to learn Ruby, but need access to the JVM for some reason (such as needing to take advantage of JVM benefits or to use the Java framework or one of its many libraries). Groovy, to me, is really more an extension of Java while JRuby, to me, really is "Ruby on the JVM."

Another interesting chart in this presentation also appears early and shows a horizontal axis representing the spectrum of dynamic to static and a vertical axis representing the spectrum of strongly typed to weakly typed. Although I don't see any notes to conclusively back up my interpretation of this slide, it does seem that the red and blue chips on the chart reflect the fact that both Groovy and (J)Ruby are strongly typed dynamic languages. Graeme Rocher has a similar but rotated slide in his Grails Exchange 2007 presentation Dynamic Groovy - Meta Magic!

This presentation has many slides covering different features that Groovy and JRuby offer as well as the often different approaches each language takes to the same features. Even without notes or the audio of the presentation, these are pretty easy to follow in the slides if you have basic familiarity with some of the key tenets of the dynamic languages.

Some of my favorite slides in this presentation occur in the "Summary" section where Ford outlines "the good" and "the bad" of each of these two languages. I am always suspicious of a presenter's credibility when he or she cannot think of much negative about whatever he or she is talking about. At the very least, nothing is perfect and there always should be situations in which a particular language is not the best fit or has disadvantages compared to another language.

Ford's "good" and "bad" for the two languages include several bullets each, but include the key differentiating characteristics of the languages. Although both will run on the JVM and allow use of Java libraries and JVM features, Groovy is closer to Java (for good or for bad) than is JRuby and JRuby is closer to Ruby. It really comes down to whether one prefers to use a Java-like language or to use Ruby on the JVM.

By the way, I couldn't help but laugh at the slide in this presentation that mentions Perl with an image of a man screaming. That's classic. Although I like both Groovy and JRuby, you won't catch me using Jperl or jPerl or any other form of Perl on the JVM anytime soon.

Diagnosing and Resolving StackOverflowError

A recent JavaWorld Community forum message (Stack Overflow after instantiating new object) reminded me that the basics of the StackOverflowError are not always understood well by people new to Java. Fortunately, the StackOverflowError is one of the easier of the runtime errors to debug and in this blog posting I will demonstrate how easy it often is to diagnose a StackOverflowError. Note that the potential for stack overflow is not limited to Java.

Diagnosing the cause of a StackOverflowError can be fairly straightfoward if the code has been compiled with the debug option turned on so that line numbers are available in the resulting stack trace. In such cases, it is typically simply a matter of finding the repeating pattern of line numbers in the stack trace. The pattern of repeating line numbers is helpful because a StackOverflowError is often caused by unterminated recursion. The repeating line numbers indicate the code that is being directly or indirectly recursively called. Note that there are situations other than unbounded recursion in which a stack overflow might occur, but this blog posting is limited to StackOverflowError caused by unbounded recursion.

The relationship of recursion gone bad to StackOverflowError is noted in the Javadoc description for StackOverflowError that states that this Error is "Thrown when a stack overflow occurs because an application recurses too deeply." It is significant that StackOverflowError ends with the word Error and is an Error (extends java.lang.Error via java.lang.VirtualMachineError) rather than a checked or runtime Exception. The difference is significant. The Error and Exception are each a specialized Throwable, but their intended handling is quite different. The Java Tutorial points out that Errors are typically external to the Java application and thus normally cannot and should not be caught or handled by the application.

I will demonstrate running into StackOverflowError via unbounded recursion with three different examples. The code used for these examples is contained in three classes, the first of which (and the main class) is shown next. I list all three classes in their entirety because line numbers are significant when debugging the StackOverflowError.

StackOverflowErrorDemonstrator.java


package dustin.examples.stackoverflow;

import java.io.IOException;
import java.io.OutputStream;

/**
* This class demonstrates different ways that a StackOverflowError might
* occur.
*/
public class StackOverflowErrorDemonstrator
{
private static final String NEW_LINE = System.getProperty("line.separator");

/** Arbitrary String-based data member. */
private String stringVar = "";

/**
* Simple accessor that will shown unintentional recursion gone bad. Once
* invoked, this method will repeatedly call itself. Because there is no
* specified termination condition to terminate the recursion, a
* StackOverflowError is to be expected.
*
* @return String variable.
*/
public String getStringVar()
{
//
// WARNING:
//
// This is BAD! This will recursively call itself until the stack
// overflows and a StackOverflowError is thrown. The intended line in
// this case should have been:
// return this.stringVar;
return getStringVar();
}

/**
* Calculate factorial of the provided integer. This method relies upon
* recursion.
*
* @param number The number whose factorial is desired.
* @return The factorial value of the provided number.
*/
public int calculateFactorial(final int number)
{
// WARNING: This will end badly if a number less than zero is provided.
// A better way to do this is shown here, but commented out.
//return number <= 1 ? 1 : number * calculateFactorial(number-1);
return number == 1 ? 1 : number * calculateFactorial(number-1);
}

/**
* This method demonstrates how unintended recursion often leads to
* StackOverflowError because no termination condition is provided for the
* unintended recursion.
*/
public void runUnintentionalRecursionExample()
{
final String unusedString = this.getStringVar();
}

/**
* This method demonstrates how unintended recursion as part of a cyclic
* dependency can lead to StackOverflowError if not carefully respected.
*/
public void runUnintentionalCyclicRecusionExample()
{
final State newMexico = State.buildState("New Mexico", "NM", "Santa Fe");
System.out.println("The newly constructed State is:");
System.out.println(newMexico);
}

/**
* Demonstrates how even intended recursion can result in a StackOverflowError
* when the terminating condition of the recursive functionality is never
* satisfied.
*/
public void runIntentionalRecursiveWithDysfunctionalTermination()
{
final int numberForFactorial = -1;
System.out.print("The factorial of " + numberForFactorial + " is: ");
System.out.println(calculateFactorial(numberForFactorial));
}

/**
* Write this class's main options to the provided OutputStream.
*
* @param out OutputStream to which to write this test application's options.
*/
public static void writeOptionsToStream(final OutputStream out)
{
final String option1 =
"1. Unintentional (no termination condition) single method recursion";
final String option2 =
"2. Unintentional (no termination condition) cyclic recursion";
final String option3 =
"3. Flawed termination recursion";
try
{
out.write((option1 + NEW_LINE).getBytes());
out.write((option2 + NEW_LINE).getBytes());
out.write((option3 + NEW_LINE).getBytes());
}
catch (IOException ioEx)
{
System.err.println("(Unable to write to provided OutputStream)");
System.out.println(option1);
System.out.println(option2);
System.out.println(option3);
}
}

/**
* Main function for running StackOverflowErrorDemonstrator.
*/
public static void main(final String[] arguments)
{
if (arguments.length < 1)
{
System.err.println(
"You must provide an argument and that single argument should be");
System.err.println(
"one of the following options:");
writeOptionsToStream(System.err);
System.exit(-1);
}

int option = 0;
try
{
option = Integer.valueOf(arguments[0]);
}
catch (NumberFormatException notNumericFormat)
{
System.err.println(
"You entered an non-numeric (invalid) option [" + arguments[0] + "]");
writeOptionsToStream(System.err);
System.exit(-2);
}

final StackOverflowErrorDemonstrator me = new StackOverflowErrorDemonstrator();
switch (option)
{
case 1 :
me.runUnintentionalRecursionExample();
break;
case 2 :
me.runUnintentionalCyclicRecusionExample();
break;
case 3 :
me.runIntentionalRecursiveWithDysfunctionalTermination();
break;
default :
System.err.println("You provided an unexpected option [" + option + "]");
}
}
}


The class above demonstrates three types of unbounded recursion: accidental and completely unintended recursion, unintended recursion associated with intentionally cyclic relationships, and intended recursion with insufficient termination condition. Each of these and their output are discussed next.

Completely Unintended Recursion

There can be times when recursion occurs with no intent of it whatsoever. A common cause might be having a method accidentally call itself. For example, it is not too difficult to get a little too careless and select an IDE's first recommendation on a return value for a "get" method that might end up being a call to that very same method! This is in fact the example shown in the class above. The getStringVar() method repeatedly calls itself until the StackOverflowError is encountered. The output will appear as follows:


Exception in thread "main" java.lang.StackOverflowError
at dustin.examples.stackoverflow.StackOverflowErrorDemonstrator.getStringVar(StackOverflowErrorDemonstrator.java:34)
at dustin.examples.stackoverflow.StackOverflowErrorDemonstrator.getStringVar(StackOverflowErrorDemonstrator.java:34)
at dustin.examples.stackoverflow.StackOverflowErrorDemonstrator.getStringVar(StackOverflowErrorDemonstrator.java:34)
at dustin.examples.stackoverflow.StackOverflowErrorDemonstrator.getStringVar(StackOverflowErrorDemonstrator.java:34)
at dustin.examples.stackoverflow.StackOverflowErrorDemonstrator.getStringVar(StackOverflowErrorDemonstrator.java:34)
at dustin.examples.stackoverflow.StackOverflowErrorDemonstrator.getStringVar(StackOverflowErrorDemonstrator.java:34)
at dustin.examples.stackoverflow.StackOverflowErrorDemonstrator.getStringVar(StackOverflowErrorDemonstrator.java:34)
at dustin.examples.stackoverflow.StackOverflowErrorDemonstrator.getStringVar(StackOverflowErrorDemonstrator.java:34)
at dustin.examples.stackoverflow.StackOverflowErrorDemonstrator.getStringVar(StackOverflowErrorDemonstrator.java:34)
at


The stack trace shown above actually is many times longer than that which I placed above, but it is simply the same repeating pattern. Because the pattern is repeating, it is easy to diagnose that line 34 of the class is the problem-causer. When we look at that line, we see that it is indeed the statement return getStringVar() that ends up repeatedly calling itself. In this case, we can quickly realize that the intended behavior was to instead return this.stringVar;.


Unintended Recursion with Cyclic Relationships

There are certain risks to having cyclic relationships between classes. One of these risks is the greater likelihood of running into unintended recursion where the cyclic dependencies are continually called between objects until the stack overflows. To demonstrate this, I use two more classes. The State class and the City class have a cyclic relationshiop because a State instance has a reference to its capital City and a City has a reference to the State in which it is located.

State.java


package dustin.examples.stackoverflow;

/**
* A class that represents a state and is intentionally part of a cyclic
* relationship between City and State.
*/
public class State
{
private static final String NEW_LINE = System.getProperty("line.separator");

/** Name of the state. */
private String name;

/** Two-letter abbreviation for state. */
private String abbreviation;

/** City that is the Capital of the State. */
private City capitalCity;

/**
* Static builder method that is the intended method for instantiation of me.
*
* @param newName Name of newly instantiated State.
* @param newAbbreviation Two-letter abbreviation of State.
* @param newCapitalCityName Name of capital city.
*/
public static State buildState(
final String newName,
final String newAbbreviation,
final String newCapitalCityName)
{
final State instance = new State(newName, newAbbreviation);
instance.capitalCity = new City(newCapitalCityName, instance);
return instance;
}

/**
* Parameterized constructor accepting data to populate new instance of State.
*
* @param newName Name of newly instantiated State.
* @param newAbbreviation Two-letter abbreviation of State.
*/
private State(
final String newName,
final String newAbbreviation)
{
this.name = newName;
this.abbreviation = newAbbreviation;
}

/**
* Provide String representation of the State instance.
*
* @return My String representation.
*/
@Override
public String toString()
{
// WARNING: This will end badly because it calls City's toString()
// method implicitly and City's toString() method calls this
// State.toString() method.
return "StateName: " + this.name + NEW_LINE
+ "StateAbbreviation: " + this.abbreviation + NEW_LINE
+ "CapitalCity: " + this.capitalCity;
}
}



City.java


package dustin.examples.stackoverflow;

/**
* Encapsulates City information and provides example of cyclic dependency.
*/
public class City
{
private static final String NEW_LINE = System.getProperty("line.separator");

/** Name of City. */
private String name;

/** Name of State the city is part of. */
private State state;

/**
* Parameterized constructor accepting parameters to populate me.
*
* @param newCityName Name of this newly instantiated city.
* @param newState State to which this city belongs.
*/
public City(
final String newCityName,
final State newState)
{
this.name = newCityName;
this.state = newState;
}

/**
* Provide String representation of this instance of City.
*
* @return My String representation.
*/
@Override
public String toString()
{
// WARNING: This will end badly because it calls State's toString()
// method implicitly and State's toString() method calls this
// City.toString() method.
return "City Name: " + this.name + NEW_LINE
+ "State: " + this.state;
}
}


In my example, the StackOverflowError occurs when the respective toString() methods of each object try to call one another. They do so repeatedly until they overflow the stack. The output from running the test is shown next:


The newly constructed State is:
Exception in thread "main" java.lang.StackOverflowError
at java.lang.StringBuilder.append(StringBuilder.java:119)
at dustin.examples.stackoverflow.City.toString(City.java:41)
at java.lang.String.valueOf(String.java:2826)
at java.lang.StringBuilder.append(StringBuilder.java:115)
at dustin.examples.stackoverflow.State.toString(State.java:62)
at java.lang.String.valueOf(String.java:2826)
at java.lang.StringBuilder.append(StringBuilder.java:115)
at dustin.examples.stackoverflow.City.toString(City.java:41)
at java.lang.String.valueOf(String.java:2826)
at java.lang.StringBuilder.append(StringBuilder.java:115)
at dustin.examples.stackoverflow.State.toString(State.java:62)
at java.lang.String.valueOf(String.java:2826)
at java.lang.StringBuilder.append(StringBuilder.java:115)
at dustin.examples.stackoverflow.City.toString(City.java:41)
at java.lang.String.valueOf(String.java:2826)
at java.lang.StringBuilder.append(StringBuilder.java:115)
at dustin.examples.stackoverflow.State.toString(State.java:62)
at java.lang.String.valueOf(String.java:2826)
at java.lang.StringBuilder.append(StringBuilder.java:115)
at dustin.examples.stackoverflow.City.toString(City.java:41)
at java.lang.String.valueOf(String.java:2826)


As with the stack trace shown in the previous example, this one actually goes on much longer than the small sample I included above. Like that previous example, the remainder was simply repeated lines of what is shown in the above sample. In this case, we can see repeated line numbers. In particular, we see that line 41 of City.java and line 62 of State.java are repeat offenders. When we look at what these lines are in these two classes, it is not surprising that it is the "return" statement in each class's respective toString implementation where the other class's toString method is implicitly invoked.

Once we see the repeating pattern and identify the cause as the cyclic toString invocations, we have several choices for fixing the situation. An obvious and easy approach is to reference portions of the "other" object rather than relying on the other object's toString. For example, we could add "get" methods to each object to return the name of the city or state and then have the toString implementations only call the getName() of the other class. We would only need to do this for one or the other to break the cycle, but we might choose that approach for both anyway.


Intended Recursion with Dysfunctional Termination Condition

Even with intentional recursion, we might run into a StackOverflowError if our terminating condition is insufficient for all cases our code might encounter. In the example in this blog posting, the everyday recursion example of implementing a factorial is used. However, the terminating condition is changed just enough to lead to problems


The factorial of -1 is: Exception in thread "main" java.lang.StackOverflowError
at dustin.examples.stackoverflow.StackOverflowErrorDemonstrator.calculateFactorial(StackOverflowErrorDemonstrator.java:49)
at dustin.examples.stackoverflow.StackOverflowErrorDemonstrator.calculateFactorial(StackOverflowErrorDemonstrator.java:49)
at dustin.examples.stackoverflow.StackOverflowErrorDemonstrator.calculateFactorial(StackOverflowErrorDemonstrator.java:49)
at dustin.examples.stackoverflow.StackOverflowErrorDemonstrator.calculateFactorial(StackOverflowErrorDemonstrator.java:49)
at dustin.examples.stackoverflow.StackOverflowErrorDemonstrator.calculateFactorial(StackOverflowErrorDemonstrator.java:49)
at dustin.examples.stackoverflow.StackOverflowErrorDemonstrator.calculateFactorial(StackOverflowErrorDemonstrator.java:49)
at dustin.examples.stackoverflow.StackOverflowErrorDemonstrator.calculateFactorial(StackOverflowErrorDemonstrator.java:49)
at dustin.examples.stackoverflow.StackOverflowErrorDemonstrator.calculateFactorial(StackOverflowErrorDemonstrator.java:49)
at dustin.examples.stackoverflow.StackOverflowErrorDemonstrator.calculateFactorial(StackOverflowErrorDemonstrator.java:49)
at


Like the other two previously displayed stack traces, only a small sample of this one is shown. The remainder of it is the same anyway.

This last StackOverflowError could have been avoided in a couple ways. First, we could have improved the termination condition to check for a passed in number less than or equal to one to return 1. The result of the factorial calculation might still not be correct, but at least it would not result in a StackOverflowError. An even better solution might be to check the passed-in integer to ensure that it is positive and throw an IllegalArgumentException if it is not.

Whether the appropriate recursion termination condition is enforced prior to applying recursion or as part of the recursion termination condition itself or both, the important point here is that all paths into the recursive functionality must be accounted for and terminated appropriately. Otherwise, recursive functionality can become unbounded and result in a StackOverflowError.


StackOverflowError sans Recursion

As I mentioned earlier, a StackOverflowError might be encountered for reasons other than unbounded recursion. In such situations, the fix will be something other than bounding recursion. Solutions might include eliminating obscenely large objects allocated on the stack or increasing the default stack size (-Xss JVM option on HotSpot JVM). Most often, however, I have seen StackOverflowError associated with uncontrolled recursion and these are often easily addressed.


Conclusion

The StackOverflowError is often one of the easier errors to debug and diagnose. Because it is commonly associated with unterminated recursion, the key to diagnosing the error is to typically look for patterns of repetitious code calls and then figure out why that series of calls never reaches a terminating condition. The StackOverflowError is a runtime error by nature. The best way to avoid it is to carefully consider one's termination conditions when using explicit recursion, be cautious when using cyclic references, and to be on the watch for accidental and completely unintended recursion. Fortunately, if an unterminated recursive condition does creep in, it is typically relatively easy to diagnose and often not too difficult to resolve.

Friday, July 3, 2009

2009 JavaOne: Still Effective Java

As evidenced by several previous blog posts (including What Makes a Great Technical Book?) I am a big fan of the book Effective Java. It therefore is not surprising that one of the first 2009 JavaOne presentations that I looked at when the slides were made available was Joshua Bloch's Effective Java: Still Effective, After All These Years (TS-5217).

This presentation begins by comparing the Second Edition of Effective Java to the First Edition in terms of number of items covered in each edition. The major new topics (including a completely overhauled chapter on concurrency) are also highlighted. I like that the Second Edition of the book contains a table at the end of the book that provides a mapping of items in the First Edition to items in the Second Edition.


Focus of Presentation

The Effective Java: Still Effective, After All These Years presentation focuses on the new items in the Second Edition: Generics, Enum Types, Variable Arguments, Concurrency, and Serialization (the "new" focus here is the Serialization Proxy Pattern). It's no surprise that the content of these slides is similar to select content from the book.


Generics

Bloch uses several slides of this presentation to cover use of wildcards with generics and covers the acronym he introduced in the second edition: PECS -> Producer Extends, Consumer Super. This mnemonic is a variation of the Get and Put Principle that Naftalin and Wadler discuss in Java Generics and Collections (one of the deepest Java books I have read).

Whether it is PECS or "Get and Put," the principle is the same: use the extends keyword with generics wildcards when retrieving data (get) from a source data structure (producer extends) or use the super keyword with generics wildcards when inserting data (put) into a data structure (consumer super). As he does in the book, Bloch points out in the slides that these generics wildcards should only be used for method arguments and not for method return values. Also, it is worth noting that it is nonsensical to have a single method argument use both extends and super.


Enums

Bloch covers some advantages of enums in this presentation. I already love the Java enum and don't need any convincing in this case. Compared to generics, enums are very simple to understand and apply. In fact, my biggest problem with enums is that I'm often tempted to stretch them past what they are intended for. I didn't see it covered in this presentation, but one of the things Bloch points out in the Second Edition of Effective Java that has really grown on me is the idea of an enum-based singleton.


Variable Arguments

Throughout Effective Java, Bloch repeatedly mentions that many of the covered items are "effective" because they move the reporting of problems to as early as possible in the process. Specifically, many of the best practices in his book lead to issues being discovered at compile time rather than at runtime. In the second edition of the book and in this presentation, Bloch points out that using variable arguments recklessly can lead to runtime problems. Specifically, he recommends always explicitly specifying the first argument of a variable arguments list as a single argument followed by varargs syntax for the remaining potential parameters of that same type when at least one is required. This prevents the runtime error if a method is called without any arguments. It will instead be discovered at compile time. In other words, the compiler can enforce the requirement of at least one argument being provided.


Concurrency / Threading

J2SE 5 saw dramatic changes to Java's concurrency support and the changes to the second edition of Effective Java reflect that. Several slides in this presentation focus on concurrency. This is the portion of the presentation where I think the liner notes from Bloch's verbal presentation would be especially helpful.


Serialization

Bloch discusses the Serialization Proxy Pattern as a better way of dealing with some common limitations associated with serialization in Java. He uses code to demonstrate the pattern in practice and also notes that this approach will not always be appropriate.


Some of My Favorite Items in Second Edition

Two of the items that the Second Edition of Effective Java newly covers that helped me justify purchasing a new edition do not seem to receive focus in this presentation, but they are covered in the excerpt available from the book itself: Chapter 2: Creating and Destroying Objects. I use the Item 2 recommendation (Builder implementation rather than telescoping constructor) and the recommendation at the very end of Item 3 (enum implementation of Singleton) relatively frequently. I also use static factories in many cases, but that was the first item in the First Edition as well.


Benefiting from this Presentation

Different Java developers are likely to benefit from this presentation in different ways. For those of us who own (or have borrowed) the Second Edition and have read it, most of this material is not new. However, it is still useful to see it again and can sometimes be helpful to see it in different form (slides rather than book pages).

For those who own the Second Edition, but have not read it, this presentation gives a taste of what's available there and might provide motivation to invest time in reading. For those who own the First Edition and are thinking about purchasing the Second Edition, this presentation provides a nice taste of the types of things newly covered in the Second Edition, though a presentation of this length could not adequately cover all the concepts and ideas introduced with the Second Edition of Effective Java.


Other Coverage

There are other resources out there that review this presentation or that are related to this presentation. They are too numerous to list them all here, but I do list a few:

JavaOne 2009: Effective Java

Effective Java, Second Edition, Chapter 2

Effective Java, Second Edition, Chapter 5

Book Excerpt and Interview: Effective Java, Second Edition

Book Review: Effective Java Second Edition

Effective Java -- Still Effective?

Photograph of Presentation