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
Monday, July 6, 2009
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.
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
The relationship of recursion gone bad to
I will demonstrate running into
StackOverflowErrorDemonstrator.java
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
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
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.java
City.java
In my example, the
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
Once we see the repeating pattern and identify the cause as the cyclic
Intended Recursion with Dysfunctional Termination Condition
Even with intentional recursion, we might run into a
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
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 sans Recursion
As I mentioned earlier, a
Conclusion
The
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
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
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
Wednesday, July 1, 2009
2009 JavaOne: Project Coin
I have enjoyed reading some of the 2009 JavaOne presentations since they have been made available online. One of the presentations I was most interested to read was Joseph Darcy's Small Language Changes in JDK Release 7: Project Coin (TS-4060). I have blogged on Project Coin previously, but am using this blog post to summarize some of the things I found most interesting about this JavaOne presentation.
Improved Dynamic Language Support on the JVM
Scripting languages on the JVM have begun to really gain traction in terms of popularity and use. One of Darcy's first slides mentions JSR 292 ("Supporting Dynamically Typed Languages on the Java Platform"), which proposes a new bytecode called invokedynamic and additional support for easier implementation of dynamic languages on the Java Virtual Machine.
Improved Modularity
The presentation also has a slide focusing on the desired improved modularity expected for Java SE 7. This was a popular topic at 2009 JavaOne as evidenced by the presentations on it (such as the one on Project Jigsaw) and by the Mark Reinhold quote "The classpath is dead." This actually is a very significant change, but it is briefly covered in this presentation.
The Elvis Operator
One of the "small features" covered in this presentation is the so-called "Elvis operator," a more concise version of the ternary operator. I find myself missing some of the features of Groovy when using traditional Java and this would be one operator that I could use in both languages if it was added. The "Elvis" operator is handy for specifying a default value that can be used when the evaluated expression is null. Like Groovy's safe navigation operator, it is a concise way to specify how to avoid unnecessary nulls. I have blogged previously about how I like to avoid the NullPointerException.
Switch on String in Java
Joe Darcy is a submitter of the proposal to add the ability to switch on String in Java. I have blogged previously regarding this versus the ability to switch on String in ActionScript. Although I find myself missing the ability to switch on a String in Java less now with the fantastic Enum and polymorphism, there are still situations I run into (often when using third-party libraries) where it would be nice to switch on a String.
Better Exception Handling
A slide in this presentation covers the proposed improvements to exception handling to allow a single catch statement to catch multiple explicitly specified exceptions. This can be much nicer than repeating code in each individual exception catch block.
Other Small Language Features Being Considered
There are a few other potential new Java SE 7 language features covered in the slides of this presentation. They include automatic resource management, type inference ("Diamond"), and list and map literals.
On Selecting What To Include
Although it is interesting to see which small language change proposals are being seriously considered, perhaps the most interesting aspect of this presentation for me is the coverage of the many things that must be considered when weighing which options to add. Darcy talks in this presentation about the importance of thinking in the big perspective rather than with limited view of what would be nice. He has a slide titled "Greed is Not Always Good" and includes perhaps the most important point to keep in mind when thinking about what one would like in Java:
"Default response is to keep the language as-is. Burden is on the proposer to convince that a change gets in; burden is not to convince to keep a change out."
I also enjoyed Darcy's slides covering all the work involved in a language change above and beyond the implementation of the feature itself. He has an overview slide in which he demonstrates the many related artifacts that must be updated such as the Java Language Specification and updating the Javadoc output. Darcy devotes several slides to each of the artifacts that need updating and then really drives the point home by using the introduction of the enum as an example. I love the enum, but it is obvious that it needed to be really desired to justify the effort.
What's Not Going to be in Java SE 7
After making a compelling case for adequately comparing the value and benefit of a particular new language feature to the cost of its introduction, Darcy has a slide in which he highlights in red some popular new features that will NOT be going into Java SE 7. These are contrasted on the same slide with features first implemented in J2SE 5. What interests me about this slide is to see where features punted from Java SE 7 (closures, reification [my favorite], and properties) rank in terms of effort against features that were implemented with J2SE 5 (enums, autoboxing/unboxing, annotation types, and generics).
Keeping Up with Project Coin and Other Java SE 7 Developments
Because Java SE 7 is still clearly a work in progress, it is not surprising that one slide in the presentation warns about forward-looking statements in the presentation. We should all be aware that any of these mentioned changes may not actually end up in Java SE 7. I have found Alex Miller's Java 7 site to be my favorite one-stop shop for the latest news on Java SE 7 developments. He apparently scours the web and blogosphere for articles that he links there and writes his own blog postings and articles as well. He currently has the status of inclusion of many proposed features listed on his page ("YES" for still planned for Java SE 7, "NO" for explicitly punted from Java SE 7, or other status if not known for certain).
Other useful sources of information include Joseph D. Darcy's Weblog, the Project Coin web page, Danny Coward's Weblog, Mark Reinhold's Blog, Neal Gafter's Blog, and Stephen Colebourne's Weblog.
Improved Dynamic Language Support on the JVM
Scripting languages on the JVM have begun to really gain traction in terms of popularity and use. One of Darcy's first slides mentions JSR 292 ("Supporting Dynamically Typed Languages on the Java Platform"), which proposes a new bytecode called invokedynamic and additional support for easier implementation of dynamic languages on the Java Virtual Machine.
Improved Modularity
The presentation also has a slide focusing on the desired improved modularity expected for Java SE 7. This was a popular topic at 2009 JavaOne as evidenced by the presentations on it (such as the one on Project Jigsaw) and by the Mark Reinhold quote "The classpath is dead." This actually is a very significant change, but it is briefly covered in this presentation.
The Elvis Operator
One of the "small features" covered in this presentation is the so-called "Elvis operator," a more concise version of the ternary operator. I find myself missing some of the features of Groovy when using traditional Java and this would be one operator that I could use in both languages if it was added. The "Elvis" operator is handy for specifying a default value that can be used when the evaluated expression is null. Like Groovy's safe navigation operator, it is a concise way to specify how to avoid unnecessary nulls. I have blogged previously about how I like to avoid the NullPointerException.
Switch on String in Java
Joe Darcy is a submitter of the proposal to add the ability to switch on String in Java. I have blogged previously regarding this versus the ability to switch on String in ActionScript. Although I find myself missing the ability to switch on a String in Java less now with the fantastic Enum and polymorphism, there are still situations I run into (often when using third-party libraries) where it would be nice to switch on a String.
Better Exception Handling
A slide in this presentation covers the proposed improvements to exception handling to allow a single catch statement to catch multiple explicitly specified exceptions. This can be much nicer than repeating code in each individual exception catch block.
Other Small Language Features Being Considered
There are a few other potential new Java SE 7 language features covered in the slides of this presentation. They include automatic resource management, type inference ("Diamond"), and list and map literals.
On Selecting What To Include
Although it is interesting to see which small language change proposals are being seriously considered, perhaps the most interesting aspect of this presentation for me is the coverage of the many things that must be considered when weighing which options to add. Darcy talks in this presentation about the importance of thinking in the big perspective rather than with limited view of what would be nice. He has a slide titled "Greed is Not Always Good" and includes perhaps the most important point to keep in mind when thinking about what one would like in Java:
"Default response is to keep the language as-is. Burden is on the proposer to convince that a change gets in; burden is not to convince to keep a change out."
I also enjoyed Darcy's slides covering all the work involved in a language change above and beyond the implementation of the feature itself. He has an overview slide in which he demonstrates the many related artifacts that must be updated such as the Java Language Specification and updating the Javadoc output. Darcy devotes several slides to each of the artifacts that need updating and then really drives the point home by using the introduction of the enum as an example. I love the enum, but it is obvious that it needed to be really desired to justify the effort.
What's Not Going to be in Java SE 7
After making a compelling case for adequately comparing the value and benefit of a particular new language feature to the cost of its introduction, Darcy has a slide in which he highlights in red some popular new features that will NOT be going into Java SE 7. These are contrasted on the same slide with features first implemented in J2SE 5. What interests me about this slide is to see where features punted from Java SE 7 (closures, reification [my favorite], and properties) rank in terms of effort against features that were implemented with J2SE 5 (enums, autoboxing/unboxing, annotation types, and generics).
Keeping Up with Project Coin and Other Java SE 7 Developments
Because Java SE 7 is still clearly a work in progress, it is not surprising that one slide in the presentation warns about forward-looking statements in the presentation. We should all be aware that any of these mentioned changes may not actually end up in Java SE 7. I have found Alex Miller's Java 7 site to be my favorite one-stop shop for the latest news on Java SE 7 developments. He apparently scours the web and blogosphere for articles that he links there and writes his own blog postings and articles as well. He currently has the status of inclusion of many proposed features listed on his page ("YES" for still planned for Java SE 7, "NO" for explicitly punted from Java SE 7, or other status if not known for certain).
Other useful sources of information include Joseph D. Darcy's Weblog, the Project Coin web page, Danny Coward's Weblog, Mark Reinhold's Blog, Neal Gafter's Blog, and Stephen Colebourne's Weblog.
Monday, June 29, 2009
Writing Code Is Much Like Writing Prose
There are many similarities when comparing the writing of code to the writing of prose. Because of this, we should be able to learn from doing each of these and apply things learned from one to the other.
The Absolutes
In writing code and in writing prose, there are a few things that are either absolute or approach very nearly the status of absolute. This is especially true for programming languages where syntactic and semantic rules must be followed for the code to be compiled and/or interpreted correctly. Even when a programming language supports certain generally frowned-upon features, some of these features are avoided to such a large degree that they almost appear absolute. For example, direct use of "goto" is generally frowned upon and is rarely seen in most code bases. However, less obvious versions of this (such as
Although it is less strictly enforced in writing prose, there still is significant pressure to conform to certain absolutes even in writing prose. For example, it is generally assumed that most professional prose will include sentences that begin with capital letters and end with periods. Similarly, proper names are almost always capitalized and correct spelling and reasonable grammar are also expected. The degree of enforcement for such things in prose often depends on the media. Professional papers and articles typically are the most enforced with the author and professional editors investing significant effort into polishing the prose. On the opposite end of the spectrum are e-mail messages, blogs, and Twitter messages, which seem to have less enforced absolutes.
The Frowned-Upon
Although there are a small number of absolutes or near-absolutes as just discussed, code development and prose writing seem to have many more things that are not absolutely avoided but seem to be strongly discouraged. However, these things tend to creep in despite their negative reputations because they do offer some advantages. Usually the advantages these items offer are ease for the writer at the expense of later reader or maintainer having more difficult prose or code.
Many developers realize problems associated with using so-called "magic numbers." However, they still seem to crop up. Often they are put in place "temporarily" and then forgotten or limited schedules prevent replacing them with a constant. These "magic numbers" are quick and easy to use when doing initial development, but can lead to a maintenance nightmare. Global variables offer a similar trade-off of easy early development at the expense of maintainability, robustness, and scalability.
Prose authoring has similar frowned-upon, but still often used, features. For example, it is often said that sentences should not end with prepositions. Similarly, it is often said that strong, active voice should be used. The tense of the writing should also be consistent. These are all things that are recommended because they do offer recognized benefits, but they are also easy to ignore or cheat on a bit when it is not deemed worth the time or effort to satisfy all of them all of the time.
The Standards
Since nearly the beginning of software development, developers have seemed to want to create and adhere to coding standards and conventions. Of course, we also seem to have been resistant to other peoples’ ideas of standards and conventions for nearly as long. The reason most of us are willing to give up some "creative freedom" and adhere to standards and conventions is that we have learned that code is more readable and maintainable (especially by others) when we adhere to a minimum set of conventions.
Prose can benefit from the same benefits of standardization and convention. There are books such as Elements of Style and Chicago Manual of Style devoted to prose style. Most of the arguments in favor of these prose writing style conventions are the same arguments used in favor of coding conventions: easier to read and maintain and consistency to benefit different readers and authors/developers.
One style issue is very similar between prose writing and code development. The subject of spaces can be surprisingly controversial in both arenas. In software development, most developers seem to agree that the optimal number of spaces for indentation is between 2 and 4 spaces. However, trying to narrow down which of these is best (2 spaces or 3 spaces or 4 spaces) is significantly more difficult.
There has been a controversy in the prose writing world regarding how many spaces should follow a period that ends one sentence before the first letter of the next sentence. I grew up thinking that two spaces was the expected number of spaces between the end of one sentence and the beginning of the next sentence. However, I was recently informed by a prose reviewer and editor that a single space is now preferred. I wondered if this was a web browser-inspired shift, but there seems to be evidence that this shift started even before the widespread adoption of HTML.
Conciseness
There seem to be differences of opinion on whether prose should be concise or verbose. To some extent, this depends on the subject of the prose. I prefer technical prose to be as concise as possible while still remaining thorough. This is especially true of technical references. However, with novels, extra verbosity can sometimes be nice to explain the story and character development. This can even go too far, for my taste, as evidenced by Moby Dick.
I have found that even in software development there is a wide diversity of opinion about conciseness of code. The longer I work in the industry, the more I value conciseness. However, I know many Java developers who don’t like the same degree of conciseness that I like. An example of this is the Java ternary operator. This operator has really grown on me, but I still know many Java developers who do not care for it at all. Although many developers are migrating to programming languages that emphasize and value conciseness, there are limits to how concise we want to be. After all, none of us are probably too excited to write and maintain production code that can be sneakily squeezed into a single line.
Refactoring
"Refactoring" is a popular term in software development, but it does have its equivalent in prose writing. In my case, I find that when I revisit my own articles, I continually "refactor" the text to make it flow better, to reduce unnecessary repetition, and to make it generally more concise. The editors of formal articles often do this to an even greater degree. In fact, the editors’ reviews often remind me of how developers are eager to change others’ peoples’ code to match their own preferences. Some of the "refactorings" I see in both development and in article editing have marginal value. However, I think most of us can agree that some "refactoring" or editing is useful and recommended for writing code or for writing prose.
When the editors and reviewers at Oracle Technology Network recommended cutting my original draft of the Basic JPA Best Practices article to less than half its original draft size, it took some effort to "refactor" that article to that point. Although some minor details and some explanatory text were removed in the process, most of the substance was retained even though the final article had half as many words as my original draft. It was not trivial trimming that draft down without losing too much substantial content, but the effort the reviewers, editors and I invested is reflected in the improvements. That article still weighs in around 11 pages, but it is leaner, tighter, and more optimized than my original draft. That sounds awfully similar to the benefits of code refactoring. The process really was like refactoring because it was more than just removing words; it involved changing words and changing sentence structure and paragraph structure.
I don’t spend much time reviewing my blog posts at the time of their writing. I think this is common among blogs, though some are exceptions. Because of this, most of us expect blog posts to be rougher than formal articles. There are definitely different expectations for different forms of writing. Similarly in code, prototypes and demonstration code can often be a little "rougher around the edges" than highly reviewed and refactored production code.
More Knowledge Means More Expressiveness
When writing prose, one of the most useful techniques for writing concise but thorough prose is to know and carefully use the appropriate words and phrases. Words have different nuances and these nuances can be used to provide more expressiveness with the same number of words. In code, we see the same thing. There is often more than one way to get the job done, but thorough understanding of the language’s features and provided class libraries allows us to select the most appropriate language feature or class that provides the exact nuanced solution appropriate to the problem at hand.
When writing prose, it is common to use well-known idioms and phrases to imply much more than the few words would normally imply. For example, "a picture is worth a thousand words" consists of only seven words but implies much more than what we might say with only seven words. Some assumed knowledge is required (readers must be familiar with the idiom) to make this work. In code, we often use design patterns and other common phrases to succinctly describe much larger ideas that otherwise would require much more description.
The Value of Review
I have found that both code and prose that I write benefit when reviewed by someone else. When I write my own code or prose, I know what I am trying to say and it all makes sense. Reviewers of articles and reviewers of code can ask questions about what is intended and provide feedback that makes the code or article more generally appealing. Sometimes we’re too close to the product for our own good and the reviewer can help us to see things that we don’t see.
"Readable" is in the Eye of the Beholder
To some degree, what is "readable" depends on the person doing the reading. This applies to both prose and code. Readers (whether reading prose or someone’s code) have their own preferences. Just as we all like different prose authors’ writing, it is not surprising that we each find different styles of code easier or more difficult to read. For example, I have an easier time reading code written by people who have similar tastes and preferences to mine. For this reason, I don’t think we’ll ever see a single programming language or framework that everyone uses. There is just too wide of a spectrum of differences of opinion for any one language or framework to appeal to everyone. This is also an important observation to realize when writing code or prose. You can try to appeal to the widest set possible, but no matter what you do there will probably be at least a small group of people who don’t like it.
Conclusion
Writing prose and writing code have much in common. Many of the same techniques that make better prose also make better code. In both cases, knowing what one has to work with (vocabulary and common phrases for prose and language features and class libraries for code) can make it easier to write particular effective prose or code. Both types of writing also benefit tremendously from review. Many of the same controversies surround both types of writing.
The Absolutes
In writing code and in writing prose, there are a few things that are either absolute or approach very nearly the status of absolute. This is especially true for programming languages where syntactic and semantic rules must be followed for the code to be compiled and/or interpreted correctly. Even when a programming language supports certain generally frowned-upon features, some of these features are avoided to such a large degree that they almost appear absolute. For example, direct use of "goto" is generally frowned upon and is rarely seen in most code bases. However, less obvious versions of this (such as
break and continue in Java) do seem to be less strictly avoided.Although it is less strictly enforced in writing prose, there still is significant pressure to conform to certain absolutes even in writing prose. For example, it is generally assumed that most professional prose will include sentences that begin with capital letters and end with periods. Similarly, proper names are almost always capitalized and correct spelling and reasonable grammar are also expected. The degree of enforcement for such things in prose often depends on the media. Professional papers and articles typically are the most enforced with the author and professional editors investing significant effort into polishing the prose. On the opposite end of the spectrum are e-mail messages, blogs, and Twitter messages, which seem to have less enforced absolutes.
The Frowned-Upon
Although there are a small number of absolutes or near-absolutes as just discussed, code development and prose writing seem to have many more things that are not absolutely avoided but seem to be strongly discouraged. However, these things tend to creep in despite their negative reputations because they do offer some advantages. Usually the advantages these items offer are ease for the writer at the expense of later reader or maintainer having more difficult prose or code.
Many developers realize problems associated with using so-called "magic numbers." However, they still seem to crop up. Often they are put in place "temporarily" and then forgotten or limited schedules prevent replacing them with a constant. These "magic numbers" are quick and easy to use when doing initial development, but can lead to a maintenance nightmare. Global variables offer a similar trade-off of easy early development at the expense of maintainability, robustness, and scalability.
Prose authoring has similar frowned-upon, but still often used, features. For example, it is often said that sentences should not end with prepositions. Similarly, it is often said that strong, active voice should be used. The tense of the writing should also be consistent. These are all things that are recommended because they do offer recognized benefits, but they are also easy to ignore or cheat on a bit when it is not deemed worth the time or effort to satisfy all of them all of the time.
The Standards
Since nearly the beginning of software development, developers have seemed to want to create and adhere to coding standards and conventions. Of course, we also seem to have been resistant to other peoples’ ideas of standards and conventions for nearly as long. The reason most of us are willing to give up some "creative freedom" and adhere to standards and conventions is that we have learned that code is more readable and maintainable (especially by others) when we adhere to a minimum set of conventions.
Prose can benefit from the same benefits of standardization and convention. There are books such as Elements of Style and Chicago Manual of Style devoted to prose style. Most of the arguments in favor of these prose writing style conventions are the same arguments used in favor of coding conventions: easier to read and maintain and consistency to benefit different readers and authors/developers.
One style issue is very similar between prose writing and code development. The subject of spaces can be surprisingly controversial in both arenas. In software development, most developers seem to agree that the optimal number of spaces for indentation is between 2 and 4 spaces. However, trying to narrow down which of these is best (2 spaces or 3 spaces or 4 spaces) is significantly more difficult.
There has been a controversy in the prose writing world regarding how many spaces should follow a period that ends one sentence before the first letter of the next sentence. I grew up thinking that two spaces was the expected number of spaces between the end of one sentence and the beginning of the next sentence. However, I was recently informed by a prose reviewer and editor that a single space is now preferred. I wondered if this was a web browser-inspired shift, but there seems to be evidence that this shift started even before the widespread adoption of HTML.
Conciseness
There seem to be differences of opinion on whether prose should be concise or verbose. To some extent, this depends on the subject of the prose. I prefer technical prose to be as concise as possible while still remaining thorough. This is especially true of technical references. However, with novels, extra verbosity can sometimes be nice to explain the story and character development. This can even go too far, for my taste, as evidenced by Moby Dick.
I have found that even in software development there is a wide diversity of opinion about conciseness of code. The longer I work in the industry, the more I value conciseness. However, I know many Java developers who don’t like the same degree of conciseness that I like. An example of this is the Java ternary operator. This operator has really grown on me, but I still know many Java developers who do not care for it at all. Although many developers are migrating to programming languages that emphasize and value conciseness, there are limits to how concise we want to be. After all, none of us are probably too excited to write and maintain production code that can be sneakily squeezed into a single line.
Refactoring
"Refactoring" is a popular term in software development, but it does have its equivalent in prose writing. In my case, I find that when I revisit my own articles, I continually "refactor" the text to make it flow better, to reduce unnecessary repetition, and to make it generally more concise. The editors of formal articles often do this to an even greater degree. In fact, the editors’ reviews often remind me of how developers are eager to change others’ peoples’ code to match their own preferences. Some of the "refactorings" I see in both development and in article editing have marginal value. However, I think most of us can agree that some "refactoring" or editing is useful and recommended for writing code or for writing prose.
When the editors and reviewers at Oracle Technology Network recommended cutting my original draft of the Basic JPA Best Practices article to less than half its original draft size, it took some effort to "refactor" that article to that point. Although some minor details and some explanatory text were removed in the process, most of the substance was retained even though the final article had half as many words as my original draft. It was not trivial trimming that draft down without losing too much substantial content, but the effort the reviewers, editors and I invested is reflected in the improvements. That article still weighs in around 11 pages, but it is leaner, tighter, and more optimized than my original draft. That sounds awfully similar to the benefits of code refactoring. The process really was like refactoring because it was more than just removing words; it involved changing words and changing sentence structure and paragraph structure.
I don’t spend much time reviewing my blog posts at the time of their writing. I think this is common among blogs, though some are exceptions. Because of this, most of us expect blog posts to be rougher than formal articles. There are definitely different expectations for different forms of writing. Similarly in code, prototypes and demonstration code can often be a little "rougher around the edges" than highly reviewed and refactored production code.
More Knowledge Means More Expressiveness
When writing prose, one of the most useful techniques for writing concise but thorough prose is to know and carefully use the appropriate words and phrases. Words have different nuances and these nuances can be used to provide more expressiveness with the same number of words. In code, we see the same thing. There is often more than one way to get the job done, but thorough understanding of the language’s features and provided class libraries allows us to select the most appropriate language feature or class that provides the exact nuanced solution appropriate to the problem at hand.
When writing prose, it is common to use well-known idioms and phrases to imply much more than the few words would normally imply. For example, "a picture is worth a thousand words" consists of only seven words but implies much more than what we might say with only seven words. Some assumed knowledge is required (readers must be familiar with the idiom) to make this work. In code, we often use design patterns and other common phrases to succinctly describe much larger ideas that otherwise would require much more description.
The Value of Review
I have found that both code and prose that I write benefit when reviewed by someone else. When I write my own code or prose, I know what I am trying to say and it all makes sense. Reviewers of articles and reviewers of code can ask questions about what is intended and provide feedback that makes the code or article more generally appealing. Sometimes we’re too close to the product for our own good and the reviewer can help us to see things that we don’t see.
"Readable" is in the Eye of the Beholder
To some degree, what is "readable" depends on the person doing the reading. This applies to both prose and code. Readers (whether reading prose or someone’s code) have their own preferences. Just as we all like different prose authors’ writing, it is not surprising that we each find different styles of code easier or more difficult to read. For example, I have an easier time reading code written by people who have similar tastes and preferences to mine. For this reason, I don’t think we’ll ever see a single programming language or framework that everyone uses. There is just too wide of a spectrum of differences of opinion for any one language or framework to appeal to everyone. This is also an important observation to realize when writing code or prose. You can try to appeal to the widest set possible, but no matter what you do there will probably be at least a small group of people who don’t like it.
Conclusion
Writing prose and writing code have much in common. Many of the same techniques that make better prose also make better code. In both cases, knowing what one has to work with (vocabulary and common phrases for prose and language features and class libraries for code) can make it easier to write particular effective prose or code. Both types of writing also benefit tremendously from review. Many of the same controversies surround both types of writing.
Friday, June 26, 2009
Java Enums Are Inherently Serializable
More than once, I have seen code such as the following (without the comments I have added to point out flaws), in which a well-intentioned Java developer has ensured that their favorite Enum explicitly declares that it is Serializable and has even provided a serialVersionUID for it.
Because enums are automatically Serializable (see Javadoc API documentation for Enum), there is no need to explicitly add the "implements Serializable" clause following the enum declaration. Once this is removed, the import statement for the java.io.Serializable interface can also be removed. If you have any doubts about

The fact that serialver returns
As mentioned above, all Enums have a

The above screen snapshot also demonstrates an advantage of running serialver against a class to generate the
Although it does not hurt anything to unnecessarily specify that an enum implements
All of the details I demonstrated and explained in this blog posting related to Enums being inherently Serializable are concisely described in two paragraphs of Section 1.12 ("Serialization of Enum Constants") of the Java Object Serialization Specification.
Additional Resources
∞ Java Object Serialization Specification
∞ Serialization of Enum Constants
∞ Object Serialization: Frequently Asked Questions
∞ Into the Mist of Serialization Myths
∞ Flatten Your Objects: Discover the Secrets of the Java Serialization API
∞ Java Serialization Algorithm Revealed
import java.io.Serializable;
/**
* Enum example with unnecessary and ignored serialization specification
* details. The Enum is already Serializable and attempts to control its
* serialization behavior are ignored. See Section 1.12 ("Serialization of Enum
* Constants") of the "Java Object Serialization Specification Version 6.0".
*/
public enum StateEnum implements Serializable
{
ALABAMA("Alabama", "AL"),
CALIFORNIA("California", "CA"),
COLORADO("Colorado", "CO"),
IDAHO("Idaho", "ID"),
UTAH("Utah", "UT"),
WYOMING("Wyoming", "WY");
// Don't do this: Don't specify serialVersionUID for enums and don't use
// an arbitrary constant such as 42L for all versions; use serialver on Sun JDK
private static final long serialVersionUID = 42L;
private String stateName;
private String stateAbbreviation;
StateEnum(final String newStateName, final String newStateAbbreviation)
{
this.stateName = newStateName;
this.stateAbbreviation = newStateAbbreviation;
}
}
Because enums are automatically Serializable (see Javadoc API documentation for Enum), there is no need to explicitly add the "implements Serializable" clause following the enum declaration. Once this is removed, the import statement for the java.io.Serializable interface can also be removed. If you have any doubts about
Enum being Serializable, run the HotSpot-provided serialver tool against your favorite enum that does not declare itself Serializable. The tool will return 0L for all enums. When a class is not Serializable, this tool returns the message "Class --yourClassNameHere-- is not Serializable." An example of this is shown in the next screen snapshot.
The fact that serialver returns
0L for the enum’s serialVersionUID indicates that the enum is indeed Serializable. The Javadoc also indicates this. A third way to prove this to yourself is to use instanceof operator as shown in the next code sample.
import java.io.Serializable;
public class UsesStateEnum
{
private StateEnum state;
public UsesStateEnum(final StateEnum newState)
{
this.state = newState;
}
public StateEnum getState()
{
return this.state;
}
public void verifyEnumIsSerializable()
{
System.out.print("StateEnum instance of Serializable? ");
System.out.println(this.state instanceof Serializable ? "yes" : "no");
}
public static void main(final String[] arguments)
{
System.out.println("Verify Enum is Serializable");
final UsesStateEnum me = new UsesStateEnum(StateEnum.COLORADO);
me.verifyEnumIsSerializable();
}
}
As mentioned above, all Enums have a
serialVersionUID of 0L. Therefore, it is not necessary to specify one as is shown in the code above. In fact, when one is specified, it is ignored anyway. The example above intentionally used the hard-coded 42L used in Joshua Bloch’s Effective Java example of how not to create a serialVersionUID. As the screen snapshot below indicates, this explicitly specified value is ignored anyway:
The above screen snapshot also demonstrates an advantage of running serialver against a class to generate the
serialVersionUID rather than making up an arbitrary long value such as 42L. By using the script, we get the 0L result for all enums and improve our chances of remembering that enums all have 0L for this value and don’t need it explicitly specified.Although it does not hurt anything to unnecessarily specify that an enum implements
Serializable or to even provide an ignored serialVersionUID, I prefer not to include these. One might argue that at least adding "implements Serializable" communicates the intent to have an enum be Serializable, but my feeling is that this is a fundamental part of the language since J2SE 5 and such communication should be unnecessary. When building a class that needs to be Serializable, using enum constituent pieces can be treated just the same as using Strings and primitives and the reference types corresponding to primitives.All of the details I demonstrated and explained in this blog posting related to Enums being inherently Serializable are concisely described in two paragraphs of Section 1.12 ("Serialization of Enum Constants") of the Java Object Serialization Specification.
Additional Resources
∞ Java Object Serialization Specification
∞ Serialization of Enum Constants
∞ Object Serialization: Frequently Asked Questions
∞ Into the Mist of Serialization Myths
∞ Flatten Your Objects: Discover the Secrets of the Java Serialization API
∞ Java Serialization Algorithm Revealed
Subscribe to:
Posts (Atom)


