Saturday, February 24, 2018

Prefer System.lineSeparator() for Writing System-Dependent Line Separator Strings in Java

JDK 7 introduced a new method on the java.lang.System class called lineSeparator(). This method does not expect any arguments and returns a String that represents "the system-dependent line separator string." The Javadoc documentation for this method also states that System.lineSeparator() "always returns the same value - the initial value of the system property line.separator." It further explains, "On UNIX systems, it returns "\n"; on Microsoft Windows systems it returns "\r\n"."

Given that a Java developer has long been able to use System.getProperty("line.separator") to get this system-dependent line separator value, why would that same Java developer now favor using System.lineSeparator instead? JDK-8198645 ["Use System.lineSeparator() instead of getProperty("line.separator")"] provides a couple reasons for favoring System.lineSeparator() over the System.getProperty(String) approach in its "Description":

A number of classes in the base module use System.getProperty("line.separator") and could use the more efficient System.lineSeparator() to simplify the code and improve performance.

As the "Description" in JDK-8198645 states, use of System.lineSeparator() is simpler to use and more efficient than System.getProperty("line.separator"). A recent message on the core-libs-dev mailing list provides more details and Roger Riggs writes in that message that System.lineSeparator() "uses the line separator from System instead of looking it up in the properties each time."

The performance benefit of using System.lineSeparator() over using System.getProperty("line.separator") is probably not all that significant in many cases. However, given its simplicity, there's no reason not to gain a performance benefit (even if tiny and difficult to measure in many cases) while writing simpler code. One of the drawbacks to the System.getProperty(String) approach is that one has to ensure that the exactly matching property name is provided to that method. With String-based APIs, there's always a risk of spelling the string wrong (I have seen "separator" misspelled numerous times as "seperator"), using the wrong case, or accidentally introducing other typos that prevent exact matches from being made.

The JDK issue that introduced this feature to JDK 7, JDK-6900043 ("Add method to return line.separator property"), also spells out some benefits in its "Description": "Querying the line.separator value is a common occurrence in large systems. Doing this properly is verbose and involves possible security failures; having a method return this value would be beneficial." Duplicate JDK-6264243 ("File.lineSeparator() to retrieve value of commonly used 'line.separator' system property") spells out advantages of this approach with even more detail and lists "correctness", "performance", and "ease of use and cross-platform development" as high-level advantages. Another duplicate issue, JDK-6529790 ("Please add LINE_SEPARATOR constant into System or some other class"), makes the point that there should be a "constant" added to "some standard Java class, as String or System," in a manner similar to that provided for file separators by File.pathSeparator.

One of the messages associated with the JDK 7 introduction of System.lineSeparator() justifies it additions with this description:

Lots of classes need to use System.getProperty("line.separator"). Many don't do it right because you need to use a doPrivileged block whenever you read a system property. Yet it is no secret - you can divine the line separator even if you have no trust with the security manager.

An interesting side note related to the addition of System.lineSeparator() in JDK 7 is that the Javadoc at that time did not indicate that the method was new to JDK 7. JDK-7082231 ("Put a @since 1.7 on System.lineSeparator") addressed this in JDK 8 and two other JDK issues (JDK-8011796 and JDK-7094275) indicate that this was desired by multiple Java developers.

The introduction of System.lineSeparator() was a very small enhancement, but it does improve the safety and readability of a relatively commonly used API while not reducing (and, in fact, while improving) performance.

Wednesday, February 21, 2018

JDK 10: FutureTask Gets a toString()

I've felt for a long time that, for most Java classes that have distinguishing attributes, developers should take the time to override Object.toString(), even if it's just with an IDE-generated implementation or using a library class such as Apache Commons Lang's ToStringBuilder. The overloaded Objects.toString() methods also make this easier than ever if one wants to implement toString by hand. The JDK class FutureTask, introduced with J2SE 5, finally gets its own toString() implementation in JDK 10.

Richard Nichols's 2012 post "How to get the running tasks for a Java Executor..." highlights the omission of a toString() method on the FutureTask class. He wrote:

It seems odd that the API doesn't include any way to gather info about what's happening inside the Executor, and also, there's not even a toString() implementation for wrapping classes like FutureTask which would bubble your Runnable or Callable classes' toString() methods.

Nichols's post is in the context of his observation that "it's quite difficult to actually expose at run-time what ... Java's Executor is actually doing at any point in time."

Issue JDK-8186326 ["Make toString() methods of "task" objects more useful"] talks about aligning FutureTask toString() with that of CompletableFuture, which the issue states "already has a useful toString method, giving the current status." An e-mail thread in late 2017 documents the discussions around the addition of toString() to FutureTask and other "task classes in j.u.c." (java.util.concurrent).

The Javadoc comments for the new FutureTask.toString() method state, "The default implementation returns a string identifying this FutureTask, as well as its completion state. The state, in brackets, contains one of the strings 'Completed Normally', 'Completed Exceptionally', 'Cancelled', or 'Not completed'." Three of these four potential completion states for FutureTask's toString() are also potentially written as part of CompletableFuture's toString() ["Cancelled" is the exception].

The addition of a specific implementation of toString() to the FutureTask class in JDK 10 is a small one. However, for a developer "staring at output of toString for 'task' objects (Runnables, Callables, Futures) when diagnosing app failures" as described in JDK-8186326's "Problem" statement, this "small" addition is likely to be very welcome.

Tuesday, February 20, 2018

JDK 10: Accessing Java Application's Process ID from Java

A popular question on StackOverflow.com is, "How can a Java program get its own process ID?" There are several answers associated with that question that include parsing the String returned by ManagementFactory.getRuntimeMXBean().getName() [but that can provide an "arbitrary string"], using ProcessHandle.getPid() [JEP 102], using Java Native Access (JNA), using System Information Gatherer And Reporter (SIGAR), using JavaSysMon, using Java Native Runtime - POSIX, parsing the results of jps (or jcmd) via invocation of Runtime.getRuntime().exec(String), and other approaches. JDK 10 introduces perhaps the easiest approach of all for obtaining a JVM process's PID via a new method on the RuntimeMXBean.

JDK-8189091 ("MBean access to the PID") introduces the RuntimeMXBean method getPid() as a default interface method with JDK 10. That issue states the "Problem" as: "The platform MBean does not provide any API to get the process ID of a running JVM. Some JMX tools rely on the hotspot implementation of RuntimeMXBean::getName which returns < pid >@< hostname >." The issue also provides the "Solution": "Introduced new API java.lang.management.RuntimeMXBean.getPid, so that JMX tools can directly get process ID instead of relying on the implementation detail, RuntimeMXBean#getName().split("@")[0]."

The next code listing is a simple one and it demonstrates use of this new getPid() method on RuntimeMXBean.

Using JDK 10's RuntimeMXBean.getPid()

final RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
final long pid = runtime.getPid();
final Console console = System.console();
out.println("Process ID is '" + pid + "' Press <ENTER> to continue.");
console.readLine();

When the code above is contained within an executable main(String[]) function and that function is executed from the command line, the output is as shown in the next screen snapshot (which also includes a separate terminal used to verify the PID is correct via jcmd).

The process ID is provided as a long and no parsing of an "arbitrary string" is necessary. This approach also does not require a third-party library or elaborate code to determine the current Java process's identifier.

This post has provided a brief introduction to what will perhaps be the easiest approach for a Java application (written with JDK 10 or later) to determine its own underlying process ID.

Monday, February 19, 2018

JDK 10's Summary Javadoc Tag

JDK 10 introduces a Javadoc tag {@summary} via issue JDK-8173425 ("Javadoc needs a new tag to specify the summary."). This new tag allows the developer to explicitly specify what portion of the Javadoc comment appears in the "summary" rather than relying on Javadoc's default treatment looking for a period and space to demarcate the end of the summary portion of the comment. JDK-8173425 states, "Currently in javadoc the summary (firstsentence) of an element is deciphered by a dot-space rule, or if required using BreakIterator." It adds that it can be confusing to know what that implicitly selected summary sentence will be.

The easiest way to see {@summary} in action may be through Javadoc examples. The next code listing shows four methods with similar Javadoc comments, two using explicit {@summary} tags and two relying on implicit Javadoc summary construction.

Demonstrating {@summary} in Javadoc Method Comments

package dustin.examples.javadoc;

/**
 * Demonstrate JDK 10 added summary support. Demonstrates
 * this by comparing similar methods' Javadoc comments with
 * and without use of new "@summary" tag.
 */
public class Summary
{
   /**
    * This method's first sentence is normally in the summary.
    * Here are some of its characteristics:
    * <ul>
    * <li>This method does great things.</li>
    * <li>This method does not really do anything.</li>
    * </ul>
    */
   public void implicitSummary1()
   {
   }

   /**
    * This method's first sentence is normally in the summary.Here are some of its characteristics:
    * <ul>
    * <li>This method does great things.</li>
    * <li>This method does not really do anything.</li>
    * </ul>
    */
   public void implicitSummary2()
   {
   }

   /**
    * {@summary This method's first sentence is normally in the summary.
    * Here are some of its characteristics:
    * <ul>
    * <li>This method does great things.</li>
    * <li>This method does not really do anything.</li>
    * </ul>}
    */
   public void explicitSummary1()
   {
   }

   /**
    * {@summary This method's first sentence is normally in the summary.Here are some of its characteristics:
    * <ul>
    * <li>This method does great things.</li>
    * <li>This method does not really do anything.</li>
    * </ul>}
    */
   public void explicitSummary2()
   {
   }
}

When the Javadoc tool delivered with the first JDK 10 (18.3) Release Candidate (Build 43) is executed against this simple class, the "Method Summary" section of the generated HTML appears as follows in a web browser.

Comparing the HTML output to the commented Java code above it demonstrates how the {@summary} allows for explicit control of what appears in the methods' summaries.

Saturday, February 17, 2018

String#repeat Coming to Java?

JDK-8197594 ("String#repeat") includes the following it its "Description": "A String method for repeating sequences of characters has been long requested with no follow through." Evidence of this interest in a method on the String class for repeating sequences of characters can be found in JDK-8197594's "Issue Links" that include JDK-8055862 ["Provide a String repeat method"] and JDK-6984084 ["(str) n times repetition of character constructor for java.lang.String"]. Both of these linked issues describe motivations for having such a method in the String class. Further evidence includes online questions such as Simple way to repeat a String in java, How to repeat string “n” times in java?, What is the simple way to repeat a string in Java?, and How do you repeat a string n number of times in Java programming?

Guava provides this desired behavior via its Strings.repeat(String, int) method and Apache Commons Lang provides this functionality via its StringUtils.repeat(String, int). It's also likely that this functionality has been implemented hundreds of times or more in individual projects. The availability of a standard java.lang.String.repeat(String, int) method could replace all of these.

The discussion on the core-libs-dev JDK mailing list regarding JDK-8197594 offers up some additional intriguing details regarding this likely addition to a future version of Java.

One interesting point is made in Jim Laskey's message in which he describes potential performance improvements that this method would provide. Specifically, Laskey writes that "performance runs with jmh ... show that these methods are significantly faster than StringBuilder equivalents" and Laskey attributes this to "fewer memory allocations," "fewer char to byte array conversions," and "faster pyramid replication vs O(N) copying." Because this is open source, the currently proposed implementation that brings these performance benefits is provided. For those who are interested, the two aforementioned open source projects have obviously made their source code available [Guava's Strings.repeat(String, int) and Apache Commons Lang's String repeat(String, int)].

Brian Goetz has posted a second reason for adding a method such as String.repeat in the standard API: to turn common functionality implemented via statements into composible expressions. Goetz explains, "My primary motivation for these sorts of methods is to take things that require execution as _statements_ (loops, if-then, etc) and turn them into _expressions_, not primarily because they are more compact, but because they are then _composible_." Goetz has described the advantages of expressions before and this is one of the primary motivations of the draft JEP related to switch expressions in Java.

A new method on java.lang.String to repeat a character sequence a specified number of times won't be as big of a deal as many other new API additions and new language features, but it can provide advantages such as not needing third-party or custom implementations, improved performance, and a standardized expression form of a commonly implemented behavior. As of this writing, JDK-8197594 is not associated with a particular Java version and is instead labeled "tbd_feature".

Friday, February 16, 2018

First JDK 10 (18.3) Release Candidate (Build 43) Demonstrates New Versioning Scheme

Mark Reinhold's post "JDK 10: First Release Candidate" announced "no unresolved P1 bugs in build 43" and named that Build 43 the initial JDK 10 Release Candidate. The Reinhold post also points to the "JDK 10 Early-Access Builds" page which contains links to the release notes; to the Javadoc-based API documentation; to the "early-access, open-source builds" (OpenJDK) for Windows, Linux, macOS, and Alpine Linux; and to the Oracle JDK builds.

The following screen snapshot shows the version information provided by the OpenJDK 10 Build 43 (the text in the screen snapshot is reproduced below the image):

openjdk version "10" 2018-03-20
OpenJDK Runtime Environment 18.3 (build 10+43)
OpenJDK 64-Bit Server VM 18.3 (build 10+43, mixed mode)

The next screen snapshot shown the version information provided by the Oracle JDK 10 Build 43 (the text in the screen snapshot is reproduced below the image):

java version "10" 2018-03-20
Java(TM) SE Runtime Environment 18.3 (build 10+43)
Java HotSpot(TM) 64-Bit Server VM 18.3 (build 10+43, mixed mode)

As the above screen snapshots show, the -version information for the OpenJDK and OracleJDK currently show both forms. They show the "10" in quotes for JDK 10, but they also show 18.3. This is consistent with the JSR 383 title ["Java SE 10 (18.3) Platform JSR (383)"] and its description.

There has been some confusion regarding the versioning scheme for versions of Java after JDK 9 because of rapid changing developments in plans for Java version names. Some key posts on the developing version naming after JDK 9 are shown below.

  1. Moving Java Forward Faster (6 September 2017)
    • Proposed that "after Java 9 we adopt a strict, time-based model with a new feature release every six months, update releases every quarter, and a long-term support release every three years."
    • "To make it clear that these are time-based releases, and to make it easy to figure out the release date of any particular release, the version strings of feature releases will be of the form $YEAR.$MONTH." This is where the "18.3" comes from in the above examples (representing March 2018).
    • Related post "Accelerating the JDK release cadence" discusses approaches to be taken with "the ultimate goal" of making "OpenJDK and Oracle JDK builds completely interchangeable."
  2. Version-string schemes for the Java SE Platform and the JDK (19 October 2017)
    • Addresses community concern and responses (such as this one) to original proposal.
    • Outlines criteria to be considered when selecting a versioning scheme.
    • Presents potential alternatives that satisfy the outlined criteria.
    • References Wadler's Law.
  3. Proposal: Newer version-string scheme for the Java SE Platform and the JDK (2 November 2017)
    • Introduces scheme $FEATURE.$INTERIM.$UPDATE.$EMERG
    • $FEATURE is "the feature-release counter, incremented every six months regardless of release content."
    • "This is primarily a time-based scheme, since $FEATURE is incremented every six months regardless of release content and, for each feature release, $UPDATE is incremented every three months."
    • JEP 223-compliant system property java.version.date is added and is the "intended GA date" in "ISO-8601 YYYY-MM-DD format." It is "some date in the future" for early access releases. In the examples above, the expected release General Availability release date is 2018-03-20.
  4. Updating the version number (1 December 2017)
    • States that JSR-383 documents will be updated to reference "10 (18.3)" instead of "18.3".
  5. Why do "Oracle JDK 10 builds" not support AppCDS? (16 February 2018)
    • I include this post because it provides a specific concrete example of how the version name differs for early access builds ("10-ea+42") versus release candidate builds intended for eventual general availability ("10+43").

The screen snapshots shown in this post depict the versions associated with the available initial build of JDK 10 Release Candidate. This initial build provides an early look at the new JDK version naming scheme in action.

Monday, February 12, 2018

APIs To Be Removed from Java 10

In the blog post "JDK 10 Release Candidate Phase", I looked at the twelve new features that are likely to be part of JDK 10. In this post, I look at some of the APIs that appear likely to be removed in JDK 10 and I look at some APIs proposed to be deprecated in JDK 10. The information in this post is based on the current version (2018/1/31 19:49 -0800 [a337d4f5aa79]) of "Java SE 10 (18.3) (JSR 383) Proposed Final Draft Specification - DRAFT" and, because this source document is a draft, this information is subject to change.

The JDK 9 enhanced deprecation feature (JEP 277) allowed several JDK APIs to be annotated with @Deprecated's new optional forRemoval() element to be set to true, which indicates that the annotated API "is earmarked for removal in a future release." The following APIs had this enhanced deprecation applied, were marked for "removal in a future release" in JDK 9, and now JDK 10 appears to be the version in which they'll be removed.

As currently proposed, JDK 10 will add the optional annotation element forRemoval=true to some previously deprecated [@Deprecated] API elements that did not formerly have forRemoval set. These include security-related interfaces, classes, and exceptions that have been replaced by other security-related constructs (many were replaced as far back as JDK 1.2). Several "finalize"-ending methods also have their @Deprecated annotation enhanced to indicate that as of JDK 10 they are "earmarked for removal in a future release." For example, FileInputStream.finalize() was deprecated in JDK 9, but will be marked with forRemoval=true as of JDK 10.

Most of the JDK API constructs to be removed in JDK 10 have been deprecated for a long time (since JDK 1.2 or earlier) and so there has been plenty of time to replace use of these. Most of the JDK API constructs newly denoted in JDK 10 to be removed in a future release have already been deprecated and this change is only to indicate that they now will likely be removed in a future release. The JDK 9-introduced enhanced deprecation mechanism allows the JDK API to have constructs more aggressively removed after having their likely removal advertised in advance via the forRemoval=true element of the @Deprecated annotation. JDK 9 removed several things and it appears likely that JDK 10 will continue the removal of certain previously deprecated API elements.