Wednesday, August 29, 2018

JDK Language Feature Preview in Action: Switch Expressions

JEP 12 ["Preview Language and VM Features"] is described on its main page as follows:

A preview language or VM feature is a new feature of the Java SE Platform that is fully specified, fully implemented, and yet impermanent. It is available in a JDK feature release to provoke developer feedback based on real world use; this may lead to it becoming permanent in a future Java SE Platform.

JEP 325 ["Switch Expressions (Preview)"] is, as the parenthetical in its title suggests, a "preview feature." As such, JEP 325 provides a high-visibility early opportunity to use the JEP 12-outlined process to preview a new language feature.

The recent messages on the OpenJDK jdk-dev mailing list provide evidence of the usefulness of JEP 325 in helping Java developers understand the implications of JEP 12 and the "preview feature" process. The discussion surrounding the "preview feature" nature of switch expressions (JEP 325) started with Mark Reinhold's August 27 message in which he wrote regarding JEP 325, "The few objections raised here are not new, having already been raised and answered over on the amber-dev and amber-spec-experts lists. I've therefore targeted this JEP to JDK 12." This message led to more feedback messages regarding objections to the currently proposed "switch expression" language implementation.

In response to some of the dialog (and specifically to a concern about not being able to change from the initial implementation once included in the JDK), Reinhold wrote in an August 28 message:

... the very point of a preview language feature is to invite further feedback without completely committing to the current design, so of course people will use it (we hope!). They're highly unlikely to use it in production, however, since preview features must be enabled explicitly, on the command line, at both compile time and run time. We're thus free to revise this design, based on new information, before it's etched into the stone of the language.

The flags currently proposed for explicitly enabling preview features for compile time and runtime are discussed in JEP 12. As currently spelled out there, compilation of preview features would require the presence of two flags passed on the command line to the javac compiler: --enable-preview and --release. The same document shows one flag needing to be passed to the java launcher at runtime to enable the preview feature: --enable-preview.

JEP 325 has already seen significant discussion on the mailing lists and I have highlighted a portion of this discussion in previous blog posts "Switch Expressions Coming to Java?" and "Enhancing Java switch Statement with Introduction of switch Expression." However, the discussion has been largely held on the amber-dev and amber-spec-experts mailing lists, so Brian Goetz has provided a summary of the previous discussion points and reasons for decisions made related to the "switch expressions" preview language feature. Goetz concluded his summary with this statement regarding the preview nature of switch expressions.

The preview mechanism will allow us to gather feedback on the feature from actual use, rather than theorizing from no examples, and potentially adjust the specification before final release if warranted. So if any _new_ issues up come as a result of actual experience, we are happy to hear about them.

In a separate (later) message, Goetz provided more background details related to the "preview feature" concept. He wrote:

A Preview language feature still needs to be Done, to the same level of Done, as a permanent feature. The difference is that we have a (short) "grace period" where we have a chance to correct serious errors that have leaked past the usual process, without having to pay the Incompatibility Penalty. With our new cadence, I expect that most non-trivial language features will go through the Preview mechanism going forward. This does not mean they are experimental, or of lower quality, or have had less thought put into them. But, it does sometimes happen that we discover unexpected interactions only after things have been tried by a broader audience, and for this, Preview gives us a short window to correct such issues if they are found early enough.

Switch Expressions (JEP 325) provides an opportunity to try out the "preview language feature" concept outlined in JEP 12. It's a feature that many people have interest in and many people have opinions on, which makes it even more interesting as a feature to take JEP 12 out for a test spin. As developers play with the preview implementation of JEP 325 now targeted for JDK 12, it'll be interesting to see how real use of the feature strengthens and weakens the arguments for the current implementation.

Friday, August 24, 2018

String.valueOf(Object) versus Objects.toString(Object)

The handy method String.valueOf(Object) has been around since JDK 1.0 and is one of the JDK-provided methods that I use on a frequent basis. I have blogged on its value before. The Objects class was introduced with JDK 1.7 and included the Objects.toString(Object) method. This post compares these two similar-sounding methods.

Both methods String.valueOf(Object) and Objects.toString(Object) essentially do the same thing: call the toString() method on a passed-in object if it's not null or return the string "null" when null is passed to them. In short, both methods are designed to provide a simple approach for invoking an object's toString() without worry about a NullPointerException if it turned out to be null.

The table below compares characteristics of the methods String.valueOf(Object) and Objects.toString(Object).

Characteristic String.valueOf(Object) Objects.toString(Object)
Java SE 10 Method Javadoc "Returns the string representation of the Object argument." "Returns the result of calling toString for a non-null argument and 'null' for a null argument."
Java SE 10 Return Javadoc "if the argument is null, then a string equal to "null"; otherwise, the value of obj.toString() is returned." "the result of calling toString for a non-null argument and "null" for a null argument"
Method Modifiers public static public static
Overloaded Versions valueOf​(boolean)
valueOf​(char)
valueOf​(char[], int, int)
valueOf​(double)
valueOf​(float)
valueOf(int)
valueOf(long)
valueOf(Object)
toString(Object)
toString(Object, String)

On the surface, it appears that String.valueOf(Object) and Objects.toString(Object) do the same thing. It turns out that they are the same. Here is the code for Objects.toString(Object) from OpenJDK:

OpenJDK: Definition of Objects.toString(Object)

public static String toString(Object o) {
    return String.valueOf(o);
}

The code snippet above shows that the Objects.toString(Object) method simply delegates to String.valueOf(Object) method. The OpenJDK implementation of String.valueOf(Object) is shown next.

OpenJDK: Definition of String.valueOf(Object)

public static String valueOf(Object obj) {
    return (obj == null) ? "null" : obj.toString();
}

The above code snippets show that either String.valueOf(Object) or Objects.toString(Object) can be called when an object's toString() representation is desired without risk of a NullPointerException. There might be minor reasons to prefer one over the other and I typically choose the direct call to String.valueOf(Object) over the indirect call to that method via Objects.toString(Object).

Although I typically use String.valueOf(Object) [instead of Objects.toString(Object)] by default when I want the string "null" returned if the passed-in object is null, the alternate overloaded method Objects.toString(Object, String) has the advantage of allowing one to specify any string to be returned by the method if the passed-in object is null. So, for example, one could use this method to return empty string (""), the string "nil", the string "none", or any other arbitrary string if a passed-in object was null. The OpenJDK code listing for Objects.toString(Object, String) is shown next.

OpenJDK: Definition of Objects.toString(Object, String)

public static String toString(Object o, String nullDefault) {
    return (o != null) ? o.toString() : nullDefault;
}

One thing to note regarding the Objects.toString(Object, String) implementation is that if one passes null to this method as the second argument, then null (rather than the string "null" or any other string) will be returned by that method.

The methods String.valueOf(Object), Objects.toString(Object), and Objects.toString(Object, String) make it easy to provide string representations of objects without the need to write explicit checks for null.

Monday, August 20, 2018

Apache Commons ArrayUtils.toString(Object) versus JDK Arrays.toString(Object)

Apache Commons Lang provides an ArrayUtils class that includes the method toString(Object) that "Outputs an array as a String." In this post, I look at situations in which this method might still be useful when the JDK provides the Arrays.toString(Object[]) method [and several overloaded versions of that method on the Arrays class for arrays of primitive types].

At one point, a reason to use the Apache Commons Lang ArrayUtils.toString(Object) method might have been that there was no alternative provided by the JDK. Arrays.toString(Object[]) was introduced with J2SE 5 (late 2004) where as Apache Commons Lang has had ArrayUtils.toString(Object) since at least Lang 2.0 (late 2003). Although there's just over a year's difference between those releases, many organizations are more willing to upgrade libraries than JDK versions, so it's possible some organizations elected to use the Lang API because they had not yet adopted JDK even after its General Availability release. By today, however, it's likely only a very, very small percentage of Java deployments are not using JDK 5 or later, so this no longer seems to be a reason to use the Apache Commons Lang method instead of the JDK method in newly written code.

Another reason Apache Commons Lang's ArrayUtils.toString(Object) might be selected over the JDK's Arrays.toString(Object[]) is the format of the string constructed from the array of elements. This doesn't seem like a very compelling motivation because the respective outputs are not that different.

For my examples in this post, I'm assuming an array of Strings defined like this:

/** Array of {@code String}s used in these demonstrations. */
private static final String[] strings
   = {"Dustin", "Inspired", "Actual", "Events"};

When the array defined above is passed to the JDK's Arrays.toString(Object[]) and to Apache Commons Lang's ArrayUtils.toString(Object), the respectively generated String representation of the array by each is compared below.

JDK Arrays.toString(Object[]) vs. ACL ArrayUtils.toString(Object)
Comparing Single String Output of Typical Java Array
Input Array JDK Arrays.toString(Object[]) Apache Commons Lang ArrayUtils.toString(Object)
{"Dustin", "Inspired", "Actual", "Events"} [Dustin, Inspired, Actual, Events] {Dustin,Inspired,Actual,Events}

The table illustrates that both methods' generated Strings are very similar in substantive terms, but there are cosmetic differences in their output. The JDK version surrounds the array contents of the generated string with square braces while the Apache Commons Lang version surrounds the array contents with curly braces. The other obvious difference is that the JDK array elements are presented in the string with a delimiter that consists of a comma and space while the Apache Commons Lang representation of the array elements delimits those elements with just a comma and no space.

If the Apache Commons Lang ArrayUtils.toString(Object) allowed the "style" of its output to be customized, that might strengthen the argument that its style of representation is an advantage. However, as can be seen in the method's implementation, it always uses ToStringStyle.SIMPLE_STYLE.

Another minor difference between the two approaches being discussed here for presenting a Java array as a single String representation is the handling of null passed to the methods. Both methods return a non-null, non-empty String when passed null, but the contents of that string differ depending on the implementation invoked. The JDK's Arrays.toString(Object[]) returns the string "null" when null is passed to it while the Apache Commons Lang's ArrayUtils.toString(Object) returns the string "{}" when null is passed to it.

The "{}" returned by ArrayUtils.toString(Object) is easy to understand and is some ways is more aesthetically pleasing for presenting the string version of null provided for an array. However, it could be argued that the "{}" implies an empty array instead of a null. The Apache Commons Language version does indeed return the same "{}" string for an empty array as well (and that matches exactly how one would declare an empty array with an array initializer). The JDK's Arrays.toString(Object[]) method provides the string "null" for null input and provides "[]" for an empty array input.

It could be argued that the JDK approach of presenting the string version of a null array parameter as "null" is more consistent with what a Java developer might expect given other similar situations in which a String representation of null is provided. Both the implicit String conversion of null (see Section 5.1.11 of Java SE 10 Language Specification for more details) and the String returned by calling String.valueOf(Object) on a null parameter present the string "null". The implicit String conversion of null for an array type results in the "null" string as well.

Another difference between ArrayUtils.toString(Object) and Arrays.toString(Object[]) is the type of the parameter expected by each method. The ArrayUtils.toString(Object) implementation expects an Object and so accepts just about anything one wants to provide to it. The JDK's Arrays.toString(Object[]), forces an array (or null) to be provided to it and non-array types cannot be provided to it. It's debatable which approach is better, but I personally generally prefer more strictly typed APIs that only allow what they advertise (help enforce their contract). In this case, because the desired functionality is to pass in an array and have a String representation of that array returned, I prefer the more definitively typed method that expects an array. On the other hand, one might argue that they prefer the method that accepts a general Object because then any arbitrary object (such as a Java collection) can be passed to the method.

In general, I don't like the idea of using a method on a class called ArrayUtils to build a String representation of anything other than an array. I have seen this method used on Java collections, but that is unnecessary as Java collections already provide reasonable toString() implementations (arrays cannot override Object's toString() and that's why they require these external methods to do so for them). It's also unnecessary to use ArrayUtils.toString(Object) to ensure that a null is handled without a NullPointerException because Objects.toString(Object) and String.valueOf(Object) handle that scenario nicely and don't pretend to be an "array" method (in fact, they don't help much with arrays).

The difference in parameter expected by each implementation that provides a String representation of a provided array leads into the motivation that I believe is most compelling for choosing the third party library-provided ArrayUtils.toString(Object) over the built-in Arrays.toString(Object[]), but it's for one specific case that this is a significant advantage: multi-dimensional Java arrays. The JDK's Arrays.toString(Object[]) is designed for a single-dimensional Java array only. The Apache Commons Lang ArrayUtils.toString(Object), however, nicely supports presenting a single String representation even of multi-dimensional Java arrays. Its method-level Javadoc advertises this advantage: "Multi-dimensional arrays are handled correctly, including multi-dimensional primitive arrays." To illustrate the differences in these methods' output for a multi-dimensional array, I'll be using this ridiculously contrived example:

/** Two-dimensional array of {@code String}s used in demonstrations. */
private static final String[][] doubleDimStrings
   = {{"Dustin"}, {"Inspired", "Actual", "Events"}};

The output from passing that two-dimensional array of Strings to the respective methods is shown in the following table.

JDK Arrays.toString(Object[]) vs. ACL ArrayUtils.toString(Object)
Comparing Single String Output of Two-Dimensional Array
Input Array JDK Arrays.toString(Object[]) Apache Commons Lang ArrayUtils.toString(Object)
{{"Dustin"}, {"Inspired", "Actual", "Events"}} [[Ljava.lang.String;@135fbaa4, [Ljava.lang.String;@45ee12a7] {{Dustin},{Inspired,Actual,Events}}

The table just shown demonstrates that the JDK's Arrays.toString() is not particularly helpful once a Java array has more than a single dimension. The Apache Commons Lang's ArrayUtils.toString(Object) is able to present a nice single String representation even of the multi-dimensional array.

I have intentionally steered clear of comparing the two alternatives covered in this post in terms of performance because I have rarely found the performance difference of these types of methods to matter in my daily work. However, if this functionality was needed in a case where every millisecond counted, then it might be worth trying each in realistic scenarios to choose the one that works best. My intuition tells me that the JDK implementation would generally perform better (especially if working with arrays of primitives and able to use one of Arrays's overloaded toString() methods intended for primitives), but my intuition has been wrong before when it comes to questions of performance.

The following table summarizes my post's discussion on characteristics of Apache Commons Lang's (version 3.7) ArrayUtils.toString(Object) and the JDK's (JDK 10) Arrays.toString(Object[]).

JDK Arrays.toString(Object[]) vs. ACL ArrayUtils.toString(Object)
Input Type JDK Arrays.toString(Object[]) Apache Commons Lang ArrayUtils.toString(Object)
Single-Dimension Array "[Dustin, Inspired, Actual, Events]" "{Dustin,Inspired,Actual,Events}"
Double-Dimension Array "[[Ljava.lang.String;@135fbaa4, [Ljava.lang.String;@45ee12a7]" "{{Dustin},{Inspired,Actual,Events}}"
null "null" "{}"
Empty Single-Dimension Array "[]" "{}"

This post has looked at some possible motivations for choosing the third-party Apache Commons Lang's ArrayUtils.toString(Object) over the built-in JDK's Arrays.toString(Object[]) for generating single String representations of arrays. I find the most obvious situation to choose this particular third-party library over the built-in alternative is for multi-dimensional arrays.

Saturday, August 18, 2018

JDK 11: Release Candidate Update and OpenJDK JDK 11 LTS

JDK 11 is scheduled to be released for General Availability on Tuesday, 25 September 2018. A 16 August 2018 Mark Reinhold message on the OpenJDK jdk-dev mailing list announced that "JDK 11 is now in the Release Candidate Phase." However, Reinhold provided updated details in a 17 August 2018 message on that same mailing list in which he stated, "We tagged the first Release Candidate build this morning (jdk-11+27), but since there are some open P1 bugs (http://j.mp/jdk-rc) it's not actually a Release Candidate." Reinhold's last message concluded, "Stay tuned ..."

The early access builds are available under "JDK 11 Early-Access Builds," but the most current version available there as of this writing (18 August 2018) is Build 26 (2018/8/9).

The "JDK 11 Release Candidate Bugs" link provided by Reinhold currently shows two P1 bugs written against JDK 11: JDK-8207317 ["SSLEngine negotiation fail Exception behavior changed from fail-fast to fail-lazy"] and JDK-8209637 ["[s390x] Interpreter doesn't call result handler after native calls"].

"Java 11" is significant from a JDK and Java SE perspective. The "Oracle Java SE Support Roadmap" states:

Beginning with Oracle Java SE 11 (18.9 LTS), the Oracle JDK will continue to be available royalty-free for development, testing, prototyping or demonstrating purposes. As announced in September 2017, with the OracleJDK and builds of Oracle OpenJDK being interchangeable for releases of Java SE 11 and later, the Oracle JDK will primarily be for commercial and support customers and OpenJDK builds from Oracle are for those who do not want commercial support or enterprise management tools.

The statement quoted above tells us that the OpenJDK and Oracle JDK are intended to be completely interchangeable as of Java SE 11. We also see that, as of Java SE 11, Oracle JDK distributions are intended for Oracle's commercial and support customers and the OpenJDK distributions are for those who do not want Oracle customer support or Oracle enterprise management tools. However, Oracle JDKs can still be used without payment for development, testing, prototyping, and demonstrations.

The "Oracle Java SE Support Roadmap" provides further details on how long Oracle support will be provided for the versions of Oracle JDK. The "Long-Term-Support (LTS) releases" are released every three years and Oracle Java SE 11 is the first such LTS version. Once Oracle Java SE 11 is released, Oracle will not provide commercial support for non-LTS Oracle SE 10.

"Oracle Java SE Support Roadmap" spells out details related to Oracle JDKs, but does not provide the same level of details related to the OpenJDK JDKs. In a message on the OpenJDK jdk-dev mailing list, Stephen Colebourne asks, "What does LTS mean for OpenJDK?" In that message, Colebourne presents some interesting questions and provides links to background references. The replies to his message provide some new details on OpenJDK JDK 11 support.

One of the responses to Colebourne's message is from Mark Reinhold. Reinhold writes that Oracle will provide "at least six months of free, GPL-licensed updates with binaries at http://jdk.java.net" for OpenJDK JDK 11. Reinhold also clarifies the the purpose of the http://jdk.java.net site: "The jdk.java.net site is for builds from Oracle, under various licenses FLOSS and otherwise. It's not part of the OpenJDK Community. Other implementors have their own distribution sites or related mechanisms."

Andrew Haley also responds to Colebourne's message and writes that "I'll say what I can" until "a public statement" can be made (presumably from Red Hat). Haley does state, "Red Hat is committed to support OpenJDK for its customers for some time. Our policy for current versions can be seen at https://access.redhat.com/articles/1299013#OpenJDK_Lifecycle_Dates_and_RHEL_versions." The provided link presents the question "Is Red Hat releasing OpenJDK 9, 10, or 11?" and answers that question, "Red Hat will skip Java SE 9 and 10, and ship an OpenJDK distribution based on Java SE 11. See the Red Hat OpenJDK 11 Advice article for additional information." Haley adds, "Given that Red Hat has an upstream first policy, we will make sure that all security patches are applied to upstream OpenJDK releases and our builds are TCK'd."

Martijn Verburg's response to Colebourne's questions is from the perspective of AdoptOpenJDK. Verburg writes that "AdoptOpenJDK offered to build, test and make available OpenJDK LTS binaries for the major (and several minor) platforms." He adds the "extra statements" that "AdoptOpenJDK will not offer commercial support" and that "AdoptOpenJDK ... will not be backporting patches."

The scheduled release of OpenJDK JDK 11 is just over a month away. With Oracle's "Commercial User End of Public Updates" for JDK 8 scheduled for January 2019, it's likely that many organizations will desire to move to JDK 11 by then.

Friday, August 17, 2018

Carefully Specify Multiple Resources in Single try-with-resources Statement

One of the more useful new features of Java 7 was the introduction of the try-with-resources statement [AKA Automatic Resource Management (ARM)]. The attractiveness of the try-with-resources statement lies in its promise to "ensure that each resource is closed at the end of the statement." A "resource" in this context is any class that implements AutoCloseable and its close() method and is instantiated inside the "try" clause of the try-with-resources statement.

The Java Language Specification [JLS] describes the try-with-resource statement in detail in Section 14.20.3 (of Java SE 10 JLS in this case). The JLS states that the "try-with-resources statement is parameterized with local variables (known as resources) that are initialized before execution of the try block and closed automatically, in the reverse order from which they were initialized, after execution of the try block."

The JLS clearly specifies that multiple resources can be defined in relation to a single try-with-resources statement and it specifies how multiple resources are specified. Specifically it indicates that try can be followed by a "ResourceSpecification" that is composed of a "ResourceList" that is composed of one or more "Resource"s. When there is more than a single declared resource, the multiple resources are delimited by semicolon (;). This specification of multiple resources in semicolon-delimited list is important because any candidate resources not declared in this manner will not be supported (will not be closed automatically) by the try-with-resources statement.

The most likely source of errors when specifying multiple resources in a try-with-resources statement is "nesting" instantiations of "resources" instead of explicitly instantiating local variables of each of them separately with semicolons between each instantiation. Examples that follow will illustrate the difference.

Two ridiculous but illustrative classes are shown next. Each class implements AutoCloseable and so can be used in conjunction with try-with-resources and will have its close() method called automatically when used correctly with the try-with-resources statement. They are named to reflect that the OuterResource can be instantiated with an instance of the InnerResource.

InnerResource.java

package dustin.examples.exceptions;

import static java.lang.System.out;

public class InnerResource implements AutoCloseable
{
   public InnerResource()
   {
      out.println("InnerResource created.");
   }

   public InnerResource(
      final RuntimeException exceptionToThrow)
   {
      throw  exceptionToThrow != null
         ? exceptionToThrow
         : new RuntimeException("InnerResource: No exception provided.");
   }

   @Override
   public void close() throws Exception
   {
      out.println("InnerResource closed.");
   }

   @Override
   public String toString()
   {
      return "InnerResource";
   }
}

OuterResource.java

package dustin.examples.exceptions;

import static java.lang.System.out;

public class OuterResource implements AutoCloseable
{
   private final InnerResource wrappedInnerResource;

   public OuterResource(final InnerResource newInnerResource)
   {
      out.println("OuterResource created.");
      wrappedInnerResource = newInnerResource;
   }

   public OuterResource(
      final InnerResource newInnerResource,
      final RuntimeException exceptionToThrow)
   {
      wrappedInnerResource = newInnerResource;
      throw  exceptionToThrow != null
           ? exceptionToThrow
           : new RuntimeException("OuterResource: No exception provided.");
   }

   @Override
   public void close() throws Exception
   {
      out.println("OuterResource closed.");
   }

   @Override
   public String toString()
   {
      return "OuterResource";
   }
}

The two classes just defined can now be used to demonstrate the difference between correctly declaring instances of each in the same try-with-resources statement in a semicolon-delimited list and incorrectly nesting instantiation of the inner resource within the constructor of the outer resource. The latter approach doesn't work as well as hoped because the inner resource without a locally defined variable is not treated as a "resource" in terms of invoking its AutoCloseable.close() method.

The next code listing demonstrates the incorrect approach for instantiating "resources" in the try-with-resources statement.

Incorrect Approach for Instantiating Resources in try-with-resources Statement

try (OuterResource outer = new OuterResource(
        new InnerResource(), new RuntimeException("OUTER")))
{
   out.println(outer);
}
catch (Exception exception)
{
   out.println("ERROR: " + exception);
}

When the code above is executed, the output "InnerResource created." is seen, but no output is ever presented related to the resource's closure. This is because the instance of InnerResource was instantiated within the call to the constructor of the OuterResource class and was never assigned to its own separate variable in the resource list of the try-with-resource statement. With a real resource, the implication of this is that the resource is not closed properly.

The next code listing demonstrates the correct approach for instantiating "resources" in the try-with-resources statement.

Correct Approach for Instantiating Resources in try-with-resources Statement

try(InnerResource inner = new InnerResource();
    OuterResource outer = new OuterResource(inner, new RuntimeException("OUTER")))
{
   out.println(outer);
}
catch (Exception exception)
{
   out.println("ERROR: " + exception);
}

When the code immediately above is executed, the output includes both "InnerResource created." AND "InnerResource closed." because the InnerResource instance was properly assigned to a variable within the try-with-resources statement and so its close() method is properly called even when an exception occurs during its instantiation.

The try-with-resources Statement section of the Java Tutorials includes a couple of examples of correctly specifying the resources in the try-with-resources as semicolon-delimited individual variable definitions. One example shows this correct approach with java.util.zip.ZipFile and java.io.BufferedWriter and another example shows this correct approach with an instances of java.sql.Statement and java.sql.ResultSet.

The introduction of try-with-resources in JDK 7 was a welcome addition to the language that it made it easier for Java developers to write resource-safe applications that were not as likely to leak or waste resources. However, when multiple resources are declared within a single try-with-resources statement, it's important to ensure that each resource is individually instantiated and assigned to its own variable declared within the try's resource specifier list to ensure that each and every resource is properly closed. A quick way to check this is to ensure that for n AutoCloseableimplementing resources specified in the try, there should be n-1 semicolons separating those instantiated resources.

Wednesday, August 8, 2018

APIs To Be Removed from Java 11

After seeing several APIs removed as part of Java 10, Java 11 (JSR 384) looks to remove some more APIs. In the recent OpenJDK java-se-spec-experts mailing list post "JSR 384 (Java SE 11) PFD Specification posted to jcp.org," Iris Clark announced the availability of the Java SE 11 (18.9) Proposed Final Draft Specification. This document lists APIs that are being removed as part of Java 11.

"Individual" (class/method) APIs are being removed in addition to the removal of entire modules.

Individual APIs Being Removed in JDK 11
Class/Method Being RemovedAdditional Notes / References
java.lang.Runtime.runFinalizersOnExit(boolean) Dangerous runFinalizersOnExit
Deprecating Java's Finalizer
java.lang.SecurityManager.checkAwtEventQueueAccess() Security Managers and Java SE JDK
JDK-8177554
JDK-8029886
JDK-8186535
java.lang.SecurityManager.checkMemberAccess(java.lang.Class,int)
java.lang.SecurityManager.checkSystemClipboardAccess()
java.lang.SecurityManager.checkTopLevelWindow(java.lang.Object)
java.lang.System.runFinalizersOnExit(boolean) Dangerous runFinalizersOnExit
Deprecating Java's Finalizer
java.lang.Thread.destroy() Thread Methods destroy() and stop(Throwable) Removed in JDK 11
java.lang.Thread.stop(java.lang.Throwable)

Module-level APIs Being Removed from Java 11
Name Module Removed Potential Third Party Replacement
JavaBeans Activation Framework (JAF) java.activation Maven Artifact
Common Object Request Broker Architecture (CORBA) java.corba glassfish-corba
Aggregator Module for other modules listed in this table java.se.ee  
Java Transaction API (JTA) java.transaction Maven Artifact
Java Architecture for XML Binding (JAXB) java.xml.bind Maven Artifact
Java API for XML Web Services (JAX-WS) java.xml.ws Maven Artifact
Common Annotations java.xml.ws.annotation Maven Artifact

JEP 320 ["Remove the Java EE and CORBA Modules"] and the StackOverflow page "Replacements for deprecated JPMS modules with Java EE APIs" provide significantly more details on replacements for the Java SE EE/CORBA-related modules.

Tuesday, August 7, 2018

JDK 12, Merging Collectors, and the Challenge of Naming

It appears likely that a new method will be available on the java.util.streams.Collectors class in JDK 12 that will, according to the new method's proposed Javadoc-based documentation, "Return a Collector that passes the input elements to two specified collectors and merges their results with the specified merge function." The currently proposed name of this new Collectors method is pairing, but that new method's name has been the source of significant discussion.

The naming of this method has solicited wide discussion on the OpenJDK core-libs-dev mailing list. Although it would be easy at first thought to label this an example of bike-shedding (or Parkinson's Law of Triviality), my experience has been that proper naming can be more important than it might first seem. I've seen many situations in which there was nothing wrong with the logic of a particular implementation, but problems ensued related to use of that implementation due to miscommunication or bad assumptions tied to poorly named code constructs. For a major API in the JDK, it's not so surprising after all that the name of this method parameter would be so seriously considered.

The discussion began with Peter Levart's post "BiCollector" (June 17), in which he opened with the question, "Have you ever wanted to perform a collection of the same Stream into two different targets using two Collectors?" Levart included an example of an implementation of such a "BiCollector" and asked if this was the type of thing that might be added to the JDK. Not surprisingly, it turns out that this is desired by others and some alternate existing implementations (Kirk Pepperdine and Tagir Valeev's streamex implementation) were mentioned.

After discussion regarding the multiple implementations of the "BiCollector," Tagir Valeev created an OpenJDK "preliminary webrev of my own implementation" and put it out for review (June 15). In that post, Valeev specifically called out that he had made up the name "pairing" for the method and added, "as I'm not a native English speaker I cannot judge whether it's optimal, so better ideas are welcome." That "opened the flood gates!"

Although there was some interesting and significant discussion surrounding other implementation details of the proposed "BiCollector" (now in proposed code as "Collectors.pairing(...)," the naming of the method received the most contributions. In a June 21 post, Valeev summarized the proposed names with accompanying comments about each recommendation and I have reproduced that list (but without the insightful comments) here:

For those interested in arguments "for" and "against" the above proposed names, I recommend viewing Valeev's original post. Most of the posts linked to above with the name suggestions provide arguments for their favored name and there is some interesting insight into what OpenJDK contributors think what aspects in a method name might aid or hinder understanding of the method.

After the excitement of naming the method, discussion died down for a while on this addition to the Collectors API until Valeev posted a "ping message" today with a link to the latest webrev for review (changes @since 11 to @since 12). In response to this "ping" message, there is feedback regarding the name of the last argument to the proposed method (currently named "finisher"), which is another reminding of the importance of naming to many of us.

Other posts on this topic on the core-libs-dev mailing list remind us that for this new method to be added to the Collectors public API, a few things still need to happen that include a sponsor volunteering to review and sponsor the change set as well as the need for a CSR (Compatibility & Specification Review) and "a couple of reviewers that are fully aware of Streams design."

A Brian Goetz post on this thread summarizes why naming this proposed method is so difficult:

The essential challenge in naming here is that this Collector does two (or maybe three) things: duplicate the stream into two identical streams ("tee"), sends each element to the two collectors ("collecting"), and then combines the results ("finishing"). So all the one-word names (pairing, teeing, unzipping, biMapping) only emphasize one half of the operation, and names that capture the full workflow accurately (teeingAndCollectingAndThen) are unwieldy.

That same Goetz post argues against "merging" (or its derivatives) for the method's name because "names along the lines of 'merging' may incorrectly give the idea that the merge is happening elementwise, rather than duplicating the streams, collecting, and merging the results."

I find several of the proposed method names to be reasonable, but there a couple that I believe (hope) were made out of an attempt at humor.

JDK-8205461 ["Create Collector which merges results of two other collectors"] is the "Enhancement" "bug" describing this issue. Its description currently begins with, "Add a new Collector into Collectors class which merges results of two other collectors" before explicitly stating, "One API method should be added (name is subject to discussion)." If you've ever wanted to name a method in a public JDK API, this might be your opportunity!

I have used this blog post in attempt to accomplish two things:

  1. Create awareness of this method that is likely to be available in the public API as of JDK 12
  2. Present an example of why naming is important and why it can be as difficult as the technical implementation
    • Proper naming can be difficult for anyone, even those of us who are native English speakers!

Although one or more names in the implementation may change, the currently proposed implementation is logically likely very close to what will eventually be delivered in conjunction with JDK-8205461.

Saturday, August 4, 2018

Project Valhalla: A First Look at L-World Value Types

In the post "JVM Language Summit 2018 and Valhalla EA Build 0", I mentioned that Project Valhalla's "L-World Value Types" Early-Access Builds are now available for Linux/x64, macOS/x64, and Windows/x64. Specifically, "Build 0 (2018/7/30)" is available for download as a "convenience." In that same post, I also mentioned that the JVM Language Summit 2018 had just wrapped up and I provided a link to one of that event's presentations: "LWorld: the next steps on the journey to Valhalla". In this post, I use code based on the Project Valhalla "L-World Value Types" Early-Access Build 0 to illustrate some of the points made in the JVM Language Summit 2018 presentation on early versions of L-World.

CAUTION: The build discussed in this post is "intended for expert users interested in Project Valhalla", is NOT intended for production, and has severe limitations and disclaimers associated with it. This build is primarily intended for those who want to "play" with L-World value types and not for other more general uses. In announcing this build on the valhalla-dev OpenJDK mailing list, David Simms described this Build 0 as follows:

"The first truly usable value type prototype" with experimental language support. Based on JDK mainline, almost complete JDK 11. This is build "0", there are bugs, performance issues, and usability issues.

The following code listing (including the __ByValue) compiles against the L-World Value Types Early Access Build 0:

package dustin.examples.valhalla;

public final __ByValue class DoubleComplex
{
   public final double real;
   public final double imaginary;
   public DoubleComplex(final double newReal, final double newImaginary)
   {
      this.real = newReal;
      this.imaginary = newImaginary;
   }
}

The L-World Value Types Early Access Build 0 javac compiler adds some methods to the DoubleComplex class shown above beyond those added by the compiler in other versions of Java. These are perhaps most easily identified by running javap against the generated class.

As the above screen snapshot demonstrates, javap tells us that several methods were added to the DoubleComplex.class class file generated from the DoubleComplex.java source file by the L-World Value Types Early Access Build 0 javac compiler:

Compiled from "DoubleComplex.java"
public final value class dustin.examples.valhalla.DoubleComplex {
  public final double real;
  public final double imaginary;
  public dustin.examples.valhalla.DoubleComplex(double, double);
  public final int hashCode();
  public final boolean equals(java.lang.Object);
  public final java.lang.String toString();
  public final long longHashCode();
  public static dustin.examples.valhalla.DoubleComplex $makeValue$(double, double);
}

Normally, we'd only expect the javap output of a .class file generated from the .java file shown above to include the two fields and the constructor that are present in the source Java file. However, the L-World Value Types Early Access Build 0 javac compiler generated a .class file with a hashCode() implementation, an equals(Object) implementation, a toString() implementation, a longHashCode() implementation (that returns long instead of the int returned by standard hashCode()), and a mysterious-looking static method $makeValue$ because of the __ByValue reference in the source code. I wasn't able to get __MakeValue to work for me in creating an instance of this value type, but I will demonstrate the other added methods in this generated class file.

I will show some output of these methods generated on value type DoubleComplex that were not explicitly specified in the Java source code file. For these output examples, the following three instances of the DoubleComplex will be used:

private final static DoubleComplex complex1
   = new DoubleComplex(15.0, 25.0);
private final static DoubleComplex complex2
   = new DoubleComplex(25.0, 35.0);
private final static DoubleComplex complex3
   = new DoubleComplex(25.0, 35.0);

The second and third instances (complex2 and complex3) have the same values and the complex1 instance has different values. Based on these instances, the methods added to ComplexDemo by the L-World Value Types EA Build 0 javac compiler generate results that look like the following:

Examples of Methods Added to Value Type)
Method Added to Value Type Results for Instances of DoubleComplex Value Type
(methods' output in bold
toString() [value class dustin.examples.valhalla.DoubleComplex, 15.0, 25.0]
[value class dustin.examples.valhalla.DoubleComplex, 25.0, 35.0]
[value class dustin.examples.valhalla.DoubleComplex, 25.0, 35.0]
equals(Object) Comparing [value class dustin.examples.valhalla.DoubleComplex, 15.0, 25.0] to [value class dustin.examples.valhalla.DoubleComplex, 25.0, 35.0]: false
Comparing [value class dustin.examples.valhalla.DoubleComplex, 25.0, 35.0] to [value class dustin.examples.valhalla.DoubleComplex, 25.0, 35.0]: true
hashCode() Complex1.hashCode(): -478263309
Complex2.hashCode(): -455358477
Complex3.hashCode(): -455358477
longHashCode() Complex1.longHashCode(): 1610134472691
Complex2.longHashCode(): 1610157377523
Complex3.longHashCode(): 1610157377523

The table above demonstrates that reasonable implementations of toString(), equals(Object), and hashCode() are provided by default for Java value types compiled with the L-World Value Types Early Access Build 0.

To run code that used my value type, I needed to use the flag -XX:+EnableValhalla in addition to specifying the JVM flag --enable-preview. If I failed to supply the -XX:+EnableValhalla flag to the L-World Value Types Early Access Build 0 java launcher, I was presented with the error message

Exception in thread "main" java.lang.ClassFormatError: Class modifier ACC_VALUE in class dustin/examples/valhalla/DoubleComplex requires option -XX:+EnableValhalla

Things You Cannot Do with Value Types in L-World Value Types EA Build 0

There are some interesting things you cannot do with the value types created with L-World Value Types Early Access Build 0 (several of these are intentional and likely to not be changed):

  • Compare two value types with ==
    • Compile-time error: "error: value types do not support =="
  • Pass value type to System.identityHashCode(Object)
    • Compile-time error: "error: value types do not support identityHashCode"
  • Synchronize on a value type
    • Compile-time error:
      error: unexpected type
           synchronized (complex1)
           ^
             required: reference
             found:    DoubleComplex
  • Value Type cannot extend another class
    • Compile-time error: "error: value type may not extend another value or class"

Class.isValue()

Although I don't demonstrate it here, there is a method available on the java.lang.Class class with this L-World Value Types Early Access Build 0 that indicates whether the class is a value type class or not. The method, Class.isValue(), returns true if the class is a value type class or false if it is NOT a value type class.

The isValue() method also appears to throw InternalErrors if it is called upon a class that is internally labeled a value type but whose Modifiers indicate it is also an interface, an abstract class, or extends a class other than Object. This implies, of course, that a value type class cannot be declared abstract ("error: illegal combination of modifiers: abstract and final" or "error: illegal combination of modifiers: abstract and value") or be an interface ("error: illegal combination of modifiers: interface and value").

L-World's Future

Although significant progress has been made in Project Valhalla related to Value Types, there is still much work to come. The JVM Language Summit presentation I cited earlier ends with discussion about "L-World major milestones" in the slides titled "L-World Roadmap." These slides and the speakers discuss major milestones "LW1", "LW10", and "LW100" and the features and characteristics expected for each of these major milestones. There will, of course, be milestones between those numbers as well. The availability of L-World Value Types Early Access Build 0 provides a convenient mechanism for interested parties to start playing with L-World value types.

Wednesday, August 1, 2018

JDK 11: Taking Single-File Java Source-Code Programs Out for a Spin

The JDK 11 Early Access Builds include functionality related to JEP 330 ("Launch Single-File Source-Code Programs"). I have written about JEP 330 before in posts "Shebang Coming to Java?" and "JEP 329 and JEP 330 Proposed for JDK 11". I get to take this feature out for a spin in this post thanks to the JDK 11 Early Access Builds.

For this demonstration, I'm using the latest (as of this writing) OpenJDK JDK 11 Early Access Build 24.

One of the first indications that support for JEP 330 is included with this JDK distribution is seen when using the -help flag (java -help):

As shown in the last image, the "help" starts with a "usage" statement and the last example in the usage statement describes how to use the Java launcher (java) to run single-file source-code programs. Specifically, the output shows the following "usage" with the usage that is the subject of this post highlighted here:

Usage: java [options] <mainclass> [args...]
           (to execute a class)
   or  java [options] -jar <jarfile> [args...]
           (to execute a jar file)
   or  java [options] -m <module>[/<mainclass>] [args...]
       java [options] --module <module>[/<mainclass>] [args...]
           (to execute the main class in a module)
   or  java [options] <sourcefile> [args]
           (to execute a single source-file program)

To demonstrate this feature, I'm going to use a simple example adapted (very slightly) from that provided in the 24 May 2018 Mario Torre post on the OpenJDK jdk-dev mailing list.

helloYou.jv

#!/bin/java
public class Hello
{
   public static void main(final String[] args)
   {
      final String name = System.console().readLine("\nPlease enter your name: ");
      System.console().printf("Hello, %s!%n", name);
   }
}

I have called this file helloYou.jv. Note that it does NOT end with the .java extension that regular Java source code files end with and I did not match the name of the file to the name of the class. In fact, I started the file's name with a lower case letter!

When I try to run this file directly with OpenJDK 11 EA-24, I see an error ("Could not find or load main class helloYou.jv"):

The following screen snapshot demonstrates that it works when I pass the flag --source=11 to the Java launcher.

I highlighted in my post "Shebang Coming to Java?" that it sounded like single-file source programs used with this JEP 330 support were not going to be allowed to end with the .java extension (which extension would be reserved for traditional Java source files). This seems to be the case as shown in the next screen snapshot where I attempt to run this feature against the same code as above, but now with the file name helloYou.java.

The last image demonstrates that we cannot run .java files with a shebang because they are treated as regular Java files and thus must meet the specification of regular Java source code files.

With this early access build, if I comment out the shebang line, I can run the now traditionally compliant Java single source code file helloYou.java (even with the .java extension and without the flag --source=11).

Had I attempted that last maneuver with OpenJDK JDK 10, attempting to run a Java source code file like that just shown would produce the error message discussed earlier: "Error: Could not find or load main class helloYou.java". I would have needed to compile the Java source code file into a .class file and would have needed to make sure it was on the classpath of the Java launcher.

This post has been a first look at the feature single-file source-code programs that is now available in the JDK 11 Early Access Builds.