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.

Tuesday, July 31, 2018

JVM Language Summit 2018 and Valhalla EA Build 0

July 2018 ended with some interesting developments related to the future of Java and the JVM. JVM Language Summit 2018 was held at Oracle's Santa Clara campus on the last two days of the month and Build 0 of the Project Valhalla "L-World Value Types" Early-Access Builds was released on July 30.

JVM Language Summit 2018

Videos of presentations from the JVM Language Summit 2018 are available on YouTube. The easiest way to access these videos is via the JVM Language Summit 2018 Playlist. The recorded presentations include the following:

Valhalla Early-Access Builds: Build 0

The Project Valhalla page now offers an early access build of the Valhalla Project. This first early access build, Build 0, was posted on July 30. The first three paragraphs of the page with this Build 0 tell us that this build is "aimed at testing a 'Value Types' implementation within the JVM" (L-World Value Types), is "provided as a convenience so that they [expert users interested in Project Valhalla] don't need to build from the source code (branch 'lworld')", and is "based on an incomplete version of JDK 11."

The Build 0 Project Valhalla Early Access Build is available as a gzip-ed TAR file for Linux/x64, Windows/x64, and macOS/x64. Although there is a long list of limitations associated with this Build 0 early access build, I'm still looking forward to playing with it.