WHAT’S NEW IN NASHORN 34 | INCUBATING HTTP/2 39 | LANGUAGE QUIZ 47
JULY/AUGUST 2017
magazine
By and for the Java community
11 17 21 28 NINE NEW MIGRATING ENHANCEMENTS JSHELL: FEATURES FROM JAVA 8 TO COLLECTIONS, THE NEW OF JDK 9 TO JAVA 9 STREAMS, AND REPL ITERATORS
ORACLE.COM/JAVAMAGAZINE //table of contents /
17 21 28 34 39 MIGRATING JAVA 9 CORE JSHELL: NASHORN WORKING FROM JAVA 8 LIBRARY READ- JAVASCRIPT WITH THE TO JAVA 9 UPDATES: EVALUATE- ENGINE IN NEW HTTP/2 By Trisha Gee COLLECTIONS PRINT LOOP JDK 9 CLIENT Step-by-step AND FOR THE JAVA By Jim Laskey By Gastón Hillar work can lead to STREAMS PLATFORM Handy additions An incubating the adoption of By Raoul-Gabriel By Constantin and support technology in all or some of the Urma and Richard Drabo for ES6 make JDK 9 promises features as you Warburton Testing code Nashorn even to make HTTP need them. Collections, snippets is now more useful. communication Streams, and part of the JDK. a lot simpler. iterators have 11 all added new NINE NEW DEVELOPER capabilities. FEATURES IN JDK 9 By Simon Ritter There’s a lot more to this release than modules.
COVER ART BY I-HUA CHEN
03 05 47 38 From the Editor Letters to the Editor Fix This User Groups The noisy, successful undertaking of Comments, questions, suggestions, By Simon Roberts The London Java Community collaborative work: Delays in the delivery and kudos Our latest code quiz 55 of major releases such as JDK 9 are 06 16 common when community is valued. Contact Us Events Java Proposals of Interest Have a comment? Suggestion? Want to Upcoming Java conferences and events JEP 241: Remove the jhat Tool submit an article proposal? Here’s how.
01
ORACLE.COM/JAVAMAGAZINE //////////////////////////////////////////// JULY/AUGUST 2017 EDITORIAL PUBLISHING Editor in Chief Associate Publisher and Audience Andrew Binstock Development Director Managing Editor Karin Kinnear +1.650.506.1985 Claire Breen Audience Development Manager Copy Editors Jennifer Kurtz Karen Perkins, Jim Donahue Technical Reviewer ADVERTISING SALES Stephen Chin Sales Director Tom Cometa DESIGN Account Manager Senior Creative Director Mark Makinney Francisco G Delgadillo Mailing-List Rentals Design Director Contact your sales representative. Richard Merchán Register Now Senior Designer RESOURCES Arianna Pucherelli Oracle Products Designer +1.800.367.8674 (US/Canada) Jaime Ferrand Oracle Services Senior Publication Designer +1.888.283.0591 (US) Sheila Brennan Oracle Code Production Designer Kathy Cygnarowicz New One-Day, Free Event | 20 Cities Globally
Explore the Latest Developer Trends:
ARTICLE SUBMISSION • DevOps, Containers, Microservices & APIs If you are interested in submitting an article, please email the editors. SUBSCRIPTION INFORMATION • MySQL, NoSQL, Oracle & Open Source Databases Subscriptions are complimentary for qualified individuals who complete the subscription form. • Development Tools & Low Code Platforms MAGAZINE CUSTOMER SERVICE [email protected] • Open Source Technologies PRIVACY Oracle Publishing allows sharing of its mailing list with selected third parties. If you prefer • Machine Learning, Chatbots & AI that your mailing address or email address not be included in this program, contact Customer Service.
Copyright © 2017, Oracle and/or its affiliates. All Rights Reserved. No part of this publication may be reprinted or otherwise reproduced without permission from the editors. JAVA MAGAZINE IS PROVIDED ON AN “AS IS” BASIS. ORACLE EXPRESSLY DISCLAIMS ALL WARRANTIES, WHETHER EXPRESS OR IMPLIED. IN NO EVENT SHALL ORACLE BE LIABLE FOR ANY Find an event near you: DAMAGES OF ANY KIND ARISING FROM YOUR USE OF OR RELIANCE ON ANY INFORMATION PROVIDED HEREIN. Opinions expressed by authors, editors, and interviewees—even if they are Oracle employees—do not necessarily reflect the views of Oracle. developer.oracle.com/code The information is intended to outline our general product direction. It is intended for information purposes only, and may not be incorporated into any contract. It is not a commitment to deliver any material, code, or functionality, and should not be relied upon in making purchasing decisions. The development, release, and timing of any features or functionality described for Oracle’s products remains at the sole discretion of Oracle. Oracle and Java are registered trademarks of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Java Magazine is published bimonthly and made available at no cost to qualified subscribers by Oracle, 500 Oracle Parkway, MS OPL-3A, Redwood City, CA 94065-1600. 02
ORACLE.COM/JAVAMAGAZINE //////////////////////////////////////////// JULY/AUGUST 2017 //from the editor /
Level Up at Oracle Code
The Noisy, Successful Undertaking Step up to modern cloud development. At the of Collaborative Work Oracle Code roadshow, Delays in the delivery of major releases such as JDK 9 expert developers lead labs and sessions on PaaS, are common when community is valued. Java, mobile, and more.
Get on the list his issue of Java Magazine is all about the previous delays triggered a great sense of frustra- for event updates: Trelease of Java 9. When I was originally laying tion. Not for me. Sure, I would have loved to have go.oracle.com/oraclecoderoadshow out the editorial schedule, this special issue was the release and this magazine come out simulta- assigned to a slot in last year’s lineup. As many of neously, and certainly I would have liked to begin you know, that intended delivery date was post- the transition to the new version with a final poned until late July of this year, which is why release of the JDK. Those sentiments, I believe, you have this issue in your hands now. We antici- are universal in the community. pated—with excitement—that this issue and the However, what lets me abide the delay with- Java 9 release would occur simultaneously. out complaint is that it derives from collaboration But this happy scenario was thwarted by an with the community. As anyone who has served unexpected development: a disagreement within on industry committees can tell you, collaborative the Java Community Process (JCP) that pushed the work is difficult, noisy, and supremely frustrat- developer.oracle.com release back until late September of this year. ing. There is nothing quite like it, except perhaps For some in the Java community, this post- parenting. Yet despite the frustrations, there is a ponement and the fact that it came after several conviction held by all parties that it is better to #developersrule
PHOTOGRAPH BY BOB ADLER/THE VERBATIM AGENCY 03
ORACLE.COM/JAVAMAGAZINE //////////////////////////////////////////// JULY/AUGUST 2017 //from the editor /
work through the hard parts of the collabora- make innovations available on a predictable tion than to abandon the effort. We are all schedule. This new approach proposes publish- better served by the collaboration than by ing whatever technology is good to go when insisting on our own preferences. the announced date arrives. Georges Saab, vice The understanding of collective benefit president of development for the Java Platform has long driven Java’s history and is indisput- group at Oracle, states that this new approach ably integral to its success. It can be easy to will be adopted in post–Java 9 releases. It will forget that the development of Java and the mean less waiting for a single central feature JVM is itself a collaborative effort. The devel- to be ready before lesser improvements are opment work is done as open source in public shipped. Ironically enough, this strategy is repositories, and the discussions about feature possible now because of the modularity in Java 9 selection, code implementations, release dates, that can localize the effects of a given change. and other points of contention are held in pub- In sum, the delays of this release are the lic mailing lists. In fact, the recent decision necessary product of the open, collaborative regarding the new release date and the spe- model that underlies Java’s success. If you’re a cific reasons for the delay were all posted and supporter of open source and open collabora- replied to on public forums. guages or their preferred approach, but rather tion, then you surely recognize that such delays Now, let me ask you, do you know of any I’m trying to underscore how unique Oracle’s are a sacrifice that the process demands. In other language whose principal corporate approach with Java is.) that sense, it is the antithesis of releasing by sponsor assigns more than 100 engineers to I recognize that my acceptance of delay in unilateral fiat. Nonetheless, I am excited that work on the language and yet defers on matters the name of collaboration is borne of an insid- modularity makes possible future releases on a of release date to a community of partners? er’s view of Java community operations. Many defined schedule while maintaining the com- There are only three companies outside of Java developers have no interest in the poli- mitment to high levels of collaboration. Oracle that have made so large a commitment tics behind release dates and couldn’t care less to language development: Apple, Google, and whether discussions are held in public or not; Andrew Binstock, Editor in Chief Microsoft. But none of them have adopted this they just want the new technology to be released [email protected] open, consensual approach. (I’m not here dep- and so are frustrated by the succession of delays. @platypusguy recating those companies’ work on their lan- This perspective is driving an initiative to 04
ORACLE.COM/JAVAMAGAZINE //////////////////////////////////////////// JULY/AUGUST 2017 //letters to the editor /
MAY/JUNE 2017 Exception Swallowing in Project Lombok low, wrap into RuntimeException, or otherwise modify In your excellent May/June 2017 issue, I want to com- any exceptions of the listed checked exception types. The magazine ment on your article “Project Lombok: Clean, Concise JVM does not check for the consistency of the checked By and for the Java community Code,” in which Josh Juneau presents a concise guide exception system; javac does, and this annotation lets you to using Lombok. On page 14, Juneau states, “The opt out of its mechanism.” @SneakyThrows annotation can be placed on a method Libraries to essentially ‘swallow’ the exceptions.” I think this Downloading Java Magazine 10 16 34 28 sentence is somewhat misleading. To me the term Two readers inquired why they could not see the LOMBOK: JDEFERRED’S DATABASE BEST PRACTICES ANNOTATIONS FOR ASYNC EVENT ACCESS WITH FOR LIBRARY CLEANER CODE MANAGEMENT STREAMS DESIGN swallow means to catch the exception, do nothing download icon for Java Magazine when they accessed ORACLE.COM/JAVAMAGAZINE with it, and continue execution of the code. the new page. Downloading the PDF version of the MAY/JUNE 2017 However, this is far from what Lombok is doing. magazine is a subscriber privilege. So you must log From the Lombok site, “Lombok will not ignore, wrap, in to access the PDF. As we have increasingly opened replace, or otherwise modify the thrown checked the magazine (making articles available without exception; it simply fakes out the compiler.” This login), you might be reading the issue without log- means we will still get an exception bubbling through ging in. To force a login, go to the quiz (which is also a should one occur, but we don’t need to explicitly han- subscriber-only benefit) and you’ll be asked to log in. dle it in calling code, much like runtime exceptions. When you do so from a laptop or desktop, you’ll see —Syed Asghar the download icon in the right margin.
Author Josh Juneau responds: “Thanks for sending me Contact Us this useful feedback. I am glad that you found the article We welcome comments, suggestions, grumbles, kudos, useful. I can certainly see why you find the termswal - article proposals, and chocolate chip cookies. All but low misleading with respect to the way in which the the last two might be edited for publication. If your @SneakyThrows annotation handles checked exceptions. note is private, indicate this in your message. Write to I do agree, after reassessing, that this was not an ideal us at [email protected]. For other ways to reach choice of words. The Lombok @SneakyThrows annotation us, see the last page of this issue. allows you to omit a try-catch clause and throw a checked exception—it does not silently swallow it. Perhaps the term hides would be more precise, as Lombok hides the requirement to code a try-catch clause by allowing you to throw a checked exception without it. As stated in the Lombok Javadoc, @SneakyThrows does not silently swal-
05
ORACLE.COM/JAVAMAGAZINE //////////////////////////////////////////// JULY/AUGUST 2017 //events /
JCrete sists of around 200 speakers and JULY 16–21 7 parallel tracks over 2 days, plus KOLYMBARI, GREEECE an additional day of workshops This loosely structured “uncon- beforehand. You will be joined by ference” involves morning ses- approximately 3,000 of your fel- sions discussing all things Java, low Java developers. Included in combined with afternoons spent the ticket price is a membership socializing, touring, and enjoy- in javaBin. ing the local scene. There is also a JCrete4Kids component for intro- Strange Loop ducing youngsters to program- SEPTEMBER 28–30 ming and Java. Attendees often ST. LOUIS, MISSOURI bring their families. Strange Loop is a multidisci- plinary conference that brings ÜberConf together the developers and JULY 18–21 thinkers building tomorrow’s DENVER, COLORADO technology in fields such as ÜberConf 2017 will be held at the emerging languages, alterna- Westin Westminster in down- tive databases, concurrency, town Denver. Topics include distributed systems, security, Java 8, microservice architectures, and the web. Talks are, in gen- JVM Language Summit Docker, cloud, security, Scala, eral, code-heavy, not process- JULY 31–AUGUST 2 Groovy, Spring, Android, iOS, oriented. A preconference day on SANTA CLARA, CALIFORNIA NoSQL, and much more. September 28 is optional and not The JVM Language Summit is an open technical collaboration among lan- included in the conference rate. guage designers, compiler writers, tool builders, runtime engineers, and JavaZone 2017 architects who target the JVM. The schedule consists of a single track of SEPTEMBER 12, WORKSHOPS NFJS Boston traditional presentations (about six each day) interspersed with workshop SEPTEMBER 13–14, CONFERENCE SEPTEMBER 29–OCTOBER 1 discussion groups. Each registrant is invited to suggest a few topics of OSLO, NORWAY BOSTON, MASSACHUSETTS interest for the workshops. JavaZone is a conference for Since 2001, the No Fluff Just Stuff Java developers created by the (NFJS) Software Symposium Tour Norwegian Java User Group, has delivered more than 450 javaBin. The conference has events with more than 70,000 existed since 2001 and now con- attendees. This event in Boston
PHOTOGRAPH BY BOB ADLER/THE VERBATIM AGENCY 06
ORACLE.COM/JAVAMAGAZINE //////////////////////////////////////////// JULY/AUGUST 2017 //events /
Oracle Code Events Oracle Code is a free event for developers to learn about the latest development technologies, practices, and trends, including containers, microservices and API applications, DevOps, databases, open source, development tools and low-code platforms, machine learning, AI, and chatbots. In addition, Oracle Code includes educational sessions for developing soft- ware in Java, Node.js, and other programming languages and frameworks using Oracle Database, MySQL, and NoSQL databases.
ASIA PACIFIC JULY 18, Sydney, Australia covers the latest trends within ing releases of Java SE, Java EE, AUGUST 10, Bangalore, India the Java and JVM ecosystem, and JavaFX; JVM languages; new AUGUST 30, Seoul, South Korea DevOps, and agile development development tools; insights into environments. recent trends in programming; and tutorials on numerous related JavaOne Java and JVM topics. in the fields of Java, micro O’Reilly Software Architecture OCTOBER 1–5 services, continuous delivery, Conference SAN FRANCISCO, CALIFORNIA JAX London and DevOps. Conference ses- OCTOBER 16–18, CONFERENCE Whether you are a seasoned OCTOBER 9–12 sions, keynotes, and expo happen AND TUTORIALS coder or a new Java programmer, LONDON, ENGLAND October 10–11. Hands-on work- OCTOBER 18–19, TRAINING JavaOne is the ultimate source of JAX London is a four-day confer- shops take place the day preced- LONDON, ENGLAND technical information and learn- ence for cutting-edge software ing and the day following the For four days, expert practitio- ing about Java. For five days, Java engineers and enterprise-level main conference. ners share new techniques and developers gather from around professionals, bringing together approaches, proven best prac- the world to talk about upcom- the world’s leading innovators tices, and exceptional technical
PHOTOGRAPH BY MASSMATT/FLICKR 07
ORACLE.COM/JAVAMAGAZINE //////////////////////////////////////////// JULY/AUGUST 2017 //events /
skills. At this conference, you’ll cutting-edge Java and web devel- hear about the best tools to use opment, software architecture, and why, and the effect they can and innovative infrastructures. have on your work. You’ll learn Experts share their professional strategies for meeting your com- experiences in sessions and work- pany’s business goals, developing shops. This year’s focus is on Java leadership skills, and making the core and enterprise technologies, conceptual jump from software the Spring ecosystem, JavaScript, developer to architect. continuous delivery, and DevOps.
KotlinConf QCon San Francisco NOVEMBER 2–3 NOVEMBER 13–15, CONFERENCE SAN FRANCISCO, CALIFORNIA NOVEMBER 16–17, WORKSHOPS October 1–5, 2017 KotlinConf is a JetBrains event SAN FRANCISCO, CALIFORNIA that provides two days of content Although the content has not San Francisco, California from Kotlin creators and commu- yet been announced, recent nity members. QCon conferences have offered #JavaOne several Java tracks along with Devoxx tracks related to web develop- NOVEMBER 6–10 ment, DevOps, cloud computing, ANTWERP, BELGIUM and more. The largest gathering of Java developers in Europe takes place Are you hosting an upcoming again this year in Antwerp. Java conference that you would Dozens of expert speakers deliver like to see included in this cal- hundreds of presentations on endar? Please send us a link Java and the JVM. Tracks include and a description of your event server-side Java, cloud, big data, at least 90 days in advance at and extensive coverage of Java 9. [email protected]. Other ways to reach us appear on the W-JAX last page of this issue. NOVEMBER 6–10 REGISTER NOW MUNICH, GERMANY W-JAX is a conference dedicated to 08
ORACLE.COM/JAVAMAGAZINE //////////////////////////////////////////// JULY/AUGUST 2017 Your Destination for Oracle and Java Expertise
Written by leading Java experts, Oracle Press books offer the most definitive, complete, and up-to-date coverage of Java available.
Java: A Beginner’s Guide, Java: The Complete OCA Java SE 8 Rapid Modernization 7th Edition Reference, Programmer I Exam Guide of Java Herb Schildt 10th Edition (Exam 1Z0-808) Applications Revised to cover Java SE 9, Herb Schildt Kathy Sierra, Bert Bates G. Venkat this book gets you started Updated for Java SE 9, this book Get complete coverage of all Adopt a high-performance programming in Java right away. shows how to develop, compile, objectives for Exam 1Z0-808. enterprise Java application debug, and run Java programs. Electronic practice exam modernization strategy. questions are included.
Available in print and eBook formats. www.OraclePressBooks.com • @OraclePress JAVA 9 Inside JDK 9
JAVA 9 FEATURES 11 | FROM JAVA 8 TO JAVA 9 17 | COLLECTIONS AND STREAMS 21 | JSHELL 28 | HTTP/2 39
his single-topic issue of Java Magazine focuses on the benefits article (page 11) provides an overview of many of these useful additions. of the new JDK 9 release other than the Java Platform Module His work is complemented by an in-depth examination (page 21) of the System (JPMS). The modularity feature, often touted as the new features in Collections, Streams, and iterators. Also, Trisha Gee central part of this release, was not yet in final approved form explains (page 17) how to compile and run Java 8 code on Java 9, even if when we went to press. So, rather than provide early informa- you’re not using modules. Ttion that might be wrong later, we’ve chosen to focus on the other parts An alternative way to run Java 9 code is with JShell, which is a new of JDK 9, which have been formal- read-evaluate-print loop (REPL) ized and finished and will ship bundled with this release. Our whenever modules are officially introduction to JShell (page 28) approved. At present, that ship- shows the basics, while our article ping date is expected to be in late on HTTP/2 (page 39) provides addi- September. The reasons for this tional examples of JShell usage. delay are discussed in the edito- The HTTP/2 technology, which rial (page 3). Shortly after that facilitates network programming, date, Java Magazine will dedicate a is part of a new incubator system second issue to Java 9, with a deep introduced in Java 9 that presents focus on the new modular archi- developers with technologies that tecture and how best to use it. are likely to be bundled in future As the articles in this issue releases. If you regularly use HTTP, demonstrate, there is a lot of take a long look at this article. goodness in Java 9 outside of mod- In addition to these articles, we ules. The language and platform also have our usual language quiz, teams have created dozens of con- events calendar, and letters to the venient new features that make editor. Enjoy, and let us know if Java programming more succinct there are other Java 9 topics you’d and enjoyable. Simon Ritter’s like us to cover in the future.
ART BY I-HUA CHEN 10
ORACLE.COM/JAVAMAGAZINE //////////////////////////////////////////// JULY/AUGUST 2017 //java 9 / Nine New Developer Features in JDK 9 There’s a lot more to this release than modules. SIMON RITTER
he big new feature in JDK 9 is the Java Platform Module myList.add(new Point(4, 4)); TSystem coupled with the introduction of the modular JDK. myList = Collections.unmodifiableList(myList); However, there are plenty of other new features in JDK 9, and in this article, I focus on nine that are of particular interest It’s not terrible, admittedly, but to create an immutable list to developers. Where applicable, I’ve included the relevant of four Points required six lines of code. JDK 9 addresses this JDK Enhancement Proposal (JEP) number so you can find through factory methods for collections. more information. This feature makes use of a change introduced in JDK 8 that enabled static methods to be included in interfaces. That Factory Methods for Collections (JEP 269) change means that you can add the necessary methods at Collections provide a well understood way for you to gather the top-level interfaces (Set, List, and Map) rather than hav- together groups (I was going to say sets, but that could be a ing to add them to a large group of classes that implement bit misleading) of data items in your applications and then those interfaces. manipulate the data in a variety of useful ways. Let’s rewrite our example using JDK 9: At the top level, there are interfaces that represent the abstract concepts of a List, Set, and Map. List
ORACLE.COM/JAVAMAGAZINE //////////////////////////////////////////// JULY/AUGUST 2017 //java 9 /
are discussed further in the article “Java 9 Core Library dropWhile() method does the Updates: Collections and Streams” (page 21). —Ed.] opposite; it drops elements from JDK 9 includes a the input stream until the test() new read-eval- Optional Class Enhancements method of the Predicate returns print loop (REPL) The Optional class was introduced in JDK 8 to reduce the true. All remaining elements of number of places where a NullPointerException could be the input stream are then passed command-line tool, generated by code (and it was frequently used to make the to the output stream. jshell, that allows you to Stream API more robust). Be careful when using either develop and test Java JDK 9 adds four new methods to Optional: of these methods when you have ■■ ifPresent(Consumer action): If there is a value present, an unordered stream. Because code interactively. perform the action using the value. the predicate needs to be sat- ■■ ifPresentOrElse(Consumer action, Runnable emptyAction): isfied only once to change the Similar to ifPresent, but if there is no value, it executes the state of elements being passed emptyAction. to the output, you might get elements in the stream that ■■ or(Supplier supplier): This method is useful when you you don’t expect, or you might miss ones you thought you want to ensure that you always have an Optional. The would get. or() method returns the same Optional if a value is The third new method is ofNullable(T t), which returns present; otherwise, it returns a new Optional created by a stream of zero or one elements, depending on whether the the supplier. value passed is null. This can be very useful to eliminate a ■■ stream(): Returns a stream of zero or one elements, null check before constructing a stream, and it is similar in a depending on whether there is a value. sense to the new stream() method in the Optional class dis- cussed in the previous section. Stream API Enhancements The last new stream method is a new version of the It’s always useful to be able to create a stream source from a static iterate() method. The version in JDK 8 took one collection of data, and JDK 8 provided several methods to do parameter as the seed and created an infinite stream as this outside the Collections API (BufferedReader.lines(), for output. JDK 9 adds an overloaded method that takes three example). Several new sources are being added in JDK 9, such parameters, which effectively gives you the ability to repli- as java.util.Scanner and java.util.regex.Matcher. cate the standard for loop syntax as a stream. For example, JDK 9 adds four methods to the Stream interface. Stream.iterate(0, i -> i < 5, i -> i + 1) gives you a First, there are two related methods: takeWhile(Pred stream of integers from 0 to 4. icate) and dropWhile(Predicate). These methods are complementary to the existing limit() and skip() meth- Read-Eval-Print Loop: jshell (JEP 222) ods, but they use a Predicate rather than a fixed integer JDK 9 includes a new read-eval-print loop (REPL) command- value. The takeWhile() method continues to take elements line tool, jshell, that allows you to develop and test Java code from the input stream and pass them to the output stream interactively, unlike when you use an IDE, where code must until the test() method of the Predicate returns true. The be edited, compiled, and then run. Developers can quickly 12
ORACLE.COM/JAVAMAGAZINE //////////////////////////////////////////// JULY/AUGUST 2017 //java 9 /
prototype sections of code as jshell Reactive streams use a publish-subscribe model in which continually reads user input, eval- The introduction the stream processor (the subscriber) subscribes to the sup- uates it, and prints either the value of private methods plier of elements (the publisher). By doing this, the supplier of the input or a description of the in interfaces will knows how many elements it can pass to the processor at any state change the input caused. time. If the supplier needs to send more than this number, To make the tool easier to allow common code it can use techniques such as local buffering or it can use an use, it includes features such as to be extracted to alternative processor (this is a typical microservice approach an editable history, tab comple- methods that will that delivers horizontal scalability by spinning up new ser- tion, automatic addition of termi- vice instances to handle increased load). nal semicolons when needed, and remain encapsulated JDK 9 includes a new class, Flow, that encloses several configurable predefined imports within the interface. interfaces: Flow.Processor, Flow.Subscriber, Flow and definitions. It is also possible .Publisher, and Flow.Subscription. A Subscription is to declare variables whose type is used to link a Publisher with a Subscriber. defined after the declaration (but The Subscription interface contains two methods: this is still not dynamic typing: once the type is set, it can’t ■■ cancel(): This method causes the Subscriber to stop be changed). receiving messages (eventually). There is even a module, jdk.jshell, that can be used if ■■ request(long n): Add n elements to the number that the you want to build your own “snippet” evaluation tool. Subscriber is able to process. This method can be called One of the most significant reasons for including a REPL repeatedly as the Subscriber processes elements and is in the JDK is to make it easier to use Java as a teaching lan- ready to process more. guage, lowering the amount of boilerplate code new develop- By implementing the Processor interface, a class can act as ers need to write before they get results. both a publisher and a subscriber, thereby acting as an inter- mediate operation in the stream. Concurrency Updates (JEP 266) The second new concurrency feature in JDK 9 consists Java 5 introduced concurrency utilities to simplify writing of enhancements to the CompletableFuture class, which was Java code that has multiple cooperating threads. Subsequent introduced in JDK 8. Several new methods relate to adding releases have improved these features by adding things such time-based functionality. These enhancements enable the as the fork/join framework in JDK 7 and, most recently, paral- use of time-outs via methods such as completeOnTimeout(), lel streams in JDK 8. Now, JDK 9 provides enhancements for delayedExecutor(), and orTimeout(). Other new methods concurrency in two areas. include failedFuture() and newIncompleteFuture(). The first is a reactive streams publish-subscribe frame- work. Processing streams of elements in an asynchronous Milling Project Coin (JEP 213) fashion can lead to problems when the rate at which elements One of the most significant changes in JDK 7 was Project are submitted to the processing code rises sharply. If the pro- Coin, which was a set of small language changes to smooth cessor is unable to handle the load, the element supplier can out some of the common tasks developers undertake repeat- be blocked or a buffer overflow situation can occur. edly in Java. The project included things such as the ability to 13
ORACLE.COM/JAVAMAGAZINE //////////////////////////////////////////// JULY/AUGUST 2017 //java 9 /
use Strings as constants in switch statements. JDK 9 builds on result in a type being inferred this and adds a few more small changes to the language syn- that is not denotable. A type The ProcessHandle tax of Java: that is not denotable can be interface identifies ■■ Effectively final variables can be used in try-with-resources represented by the compiler, and provides control of without being reassigned. Currently, each resource that but it cannot be expressed to is used must be assigned to a new variable, even if that the JVM using the class signa- native processes. resource has already been defined in the method. With this ture attribute. In JDK 9, it is now change, it is now possible to use an existing variable (as possible to use the diamond long as it is effectively final) without reassigning it. Here is operator with an anonymous an example of the change: class as long as the inferred type is denotable, for example:
try (Resource r = alreadyDefinedResource) ... List
try (alreadyDefinedResource) ... ■■ A single underscore will no longer be valid as an identifier. I often ask, during Java 9 presentations, if anyone has ever ■■ Private methods can be used in interfaces. Interfaces used a single underscore as a variable name and, thank- changed in a big way in JDK 8. First, there was the introduc- fully, few people have. The reason for doing this is that in a tion of default methods, which allowed new methods to be later release of the JDK (presumably JDK 10), it will be valid added to existing interfaces without forcing a break in back- to use a single underscore as a variable name only in lambda ward compatibility. Because this meant that behavior could expressions. This makes sense. You could use a single be included in an interface (giving Java multiple-inheritance underscore if your lambda expression takes only one argu- of behavior for the first time), it was also logical to include ment and you don’t use the argument in the body of the static methods. In JDK 9, the introduction of private meth- lambda, for example: ods in interfaces will allow common code to be extracted to methods that will remain encapsulated within the interface. _ -> getX() ■■ The diamond operator can be used with anonymous classes. One of the things included in JDK 8 and now JDK 9 is better (For those of you who like the idea of underscores as vari- type inference. Being able to use lambda expressions with- able names, you can still use two or more as an identifier.) out explicitly specifying the types of parameters is a good ■■ Extended use of the @SafeVarargs annotation is allowed. example of this. This ability required a substantial rewrite Currently, this annotation can be used only on constructors, of how the Java compiler processes type inference, and the static methods, and final methods, none of which can be diamond operator change in JDK 9 makes use of that com- overridden. Because a private method cannot be overridden piler change. The problem, as it existed before, was that by a subclass, it is logical also to enable private methods to using the diamond operator with an anonymous class could use this annotation. 14
ORACLE.COM/JAVAMAGAZINE //////////////////////////////////////////// JULY/AUGUST 2017 //java 9 /
Spin-Wait Hints (JEP 285) compare-and-set operations, but without the performance This is a small change because it adds only a single method, overhead that is associated with using the equivalent classes but its addition to the Thread class is significant. The other and methods of the java.util.concurrent.atomic package. interesting aspect of this feature is that it is the first JEP to be You can also use a VarHandle to “fence” operations, giv- included that was proposed by a company other than Oracle ing you fine-grained control over the memory ordering of (in this case, Azul Systems). operations such as read and write or store and load. This can The onSpinWait() method provides a hint to the JVM that be useful in situations where you don’t want the Java compiler the thread is currently in a processor spin loop. If the JVM and or JVM to reorder operations, which is often done to optimize hardware platform support optimizations when spinning, the performance of code paths. such hints can be used; otherwise, the call is ignored. Typical optimizations include reducing thread-to-thread latencies Process API Updates (JEP 102) and reducing power consumption. JDK 9 contains enhancements to the Process and ProcessBuilder classes and introduces a new ProcessHandle Variable Handles (JEP 193) interface. ProcessBuilder now includes the method One of the most significant changes in JDK 9 caused by mod- startAsPipeline(). As the name suggests, this method ularizing the core JDK libraries is the encapsulation of the constructs a UNIX-style pipeline of processes using a list of internal APIs by default. Probably the most well known of ProcessBuilders. As each process is started, its standard out- these is sun.misc.Unsafe. To make some of the functionality put is connected to the standard input of the next process. of this private API available through a public API, JDK 9 intro- Here’s a simple example that pipes the output of the duces the VarHandle class. UNIX/Linux ls command on /tmp through wc –l to get a Variables are used in Java all the time. They are implicit count of the number of files in the tmp directory: pointers to areas of memory that hold values. A variable han- dle is a typed reference to a variable (so for those who’ve used ProcessBuilder ls = new ProcessBuilder() C and C++, it’s effectively a pointer to a pointer). .command("ls") In order to get a reference to a VarHandle, you use the .directory(Paths.get("/tmp").toFile()); MethodHandle.Lookup class that has been extended in JDK 9. ProcessBuilder wc = new ProcessBuilder() You can retrieve references to .command("wc", "-l") either static or nonstatic vari- .redirectOutput(Redirect.INHERIT); ables, as required, as well as With features such List
ORACLE.COM/JAVAMAGAZINE //////////////////////////////////////////// JULY/AUGUST 2017 //java 9 / //java proposals of interest /
The subinterface ProcessHandle.Info provides a range of process-specific details, such as the command line used to start the process, when the process started, and the identity FEATURED JDK ENHANCEMENT PROPOSAL of the user that started the process. The Process class has seven new methods that pro- JEP 241: Veteran Tool jhat vide access to more information about the native process. Some of these overlap with those available through the Reaches Retirement ProcessHandle: ■■ children() and descendants(): Lists the process’s children The release of JDK 9 contains lots of goodies, as this or dependents, respectively issue of Java Magazine has reported in detail. However, ■■ getPid(): Returns the ID of the given process due to the approval of JDK Enhancement Proposal 241 ■■ info(): Returns a snapshot of information as a Process (JEP 241), the jhat heap analysis tool will no longer be Handle.Info instance bundled. jhat originally made its way into the JDK with ■■ onExit(): Is a CompletableFuture that can be used to per- the release of Java 6. It came from a project called HAT form tasks when the process terminates and was a part of the now defunct javatools projects ■■ supportsNormalTermination(): Determines whether before its incorporation into the JDK. destroy() terminates the process normally Despite its inclusion in recent releases of the JDK, ■■ toHandle(): Returns the ProcessHandle of this process it was always categorized as an experimental tool and labeled as such in all official documentation. Over the Conclusion years, other heap profilers have surpassed it, and so jhat As you can see, there are many useful and powerful new has been in an extended decline with little maintenance features included in JDK 9 that are particularly targeted at being accorded to it. developers. With features such as these, you might want to If you’re still using jhat, you should consider other consider migrating your development to this release as soon tools. Two worthy options are VisualVM and, at a pro- as you can. grammatic level, the Java HotSpot Serviceability Agent API. The latter is thoroughly explored and documented Simon Ritter (@speakjava) is the deputy CTO of Azul Systems. in the book Java Performance Companion, which was He has been in the IT business since 1984 and holds a BS in phys- reviewed in the September/October 2016 issue. ics from Brunel University in the UK. He joined Sun Microsystems Standalone commercial offerings are also available, in 1996 and spent time working in both Java development and notably JProfiler and YourKit. In addition, leading IDEs consultancy. Ritter has been presenting Java technologies to today bundle tools that enable you to examine the JVM developers since 1999, focusing on the core Java platform as well heap in developer-friendly ways. as client and embedded applications. One way or the other, you should be able to find good substitutes for jhat.
16
ORACLE.COM/JAVAMAGAZINE //////////////////////////////////////////// JULY/AUGUST 2017 //java 9 / Migrating from Java 8 to Java 9 Step-by-step work can lead to the adoption of all or some of the features even without using modules.
TRISHA GEE his article shows the steps you take to run Java 8 code and Compiler warnings. First, of course, you can look at any com- Tuse some of the new features of Java 9 without migrating piler warnings, because some of those will tell you about to modules. I principally examine what you need to do to get potential problems (see Figure 1). the code compiling and running. I’m using my IDE, IntelliJ IDEA, to compile the code and to show me the warnings, but what you see in the messages Getting Started box in Figure 1 is the same as what you’d see using javac from First, download and install the latest version of JDK 9. At the the command line. Other IDEs, such as NetBeans and Eclipse, time of this writing, it is still an Early Access release and can will have similar functionality. In Figure 1, you can see that be found here (in this article, I’m using build 9-ea+166). the code has a field with a single underscore as a name. This Until the impact of Java 9 on your system is under- single-underscore name has been removed as a legal identi- stood, you probably don’t want it to be the default Java version. So, instead of updating $JAVA_HOME to point to the new installation, you might want to create a new environment variable, $JAVA9_HOME, instead. I’ll be using this approach throughout this article. You should also look at this detailed migration guide to get a feel for what steps might be needed.
Before Jumping In You can determine the amount of effort that might be required to migrate to Java 9 without even downloading or using it. There are several tools avail- able in Java 8 that will give you appro- PHOTOGRAPH BY JOHN BLYTHE priate hints. Figure 1. Example compiler warning about a potential problem 17
ORACLE.COM/JAVAMAGAZINE //////////////////////////////////////////// JULY/AUGUST 2017 //java 9 /
fier name in Java 9 as part of JDK Enhancement Proposal (JEP) I navigate to the location of my class files via the command 213. This is because underscores might be used in a later ver- line (Figure 2 shows that this is %PROJECT%\%MODULE%\build\ sion of Java to make working with lambda expressions even classes) and from there, I run jdeps with the -jdkinternals easier. If you come across identifier names that consist of flag. I’m using Windows, so my command line is the fol- only a single underscore, you’ll need to rename them. Note lowing, where main is the name of the directory containing that names containing underscores, for example _fieldName, my classes: are still valid; the problem is identifier names that contain only an underscore and nothing else. > %JAVA_HOME%\bin\jdeps -jdkinternals main Identify problematic dependencies with jdeps. One of the goals of this release, and surely the most famous Java 9 feature, When I run this command, I get the output in Figure 3. is to allow the JDK developers to hide internal implementa- These messages indicate that my TwitterOAuth class tion details. In the past, developers were expected to follow is using the internal classes sun.misc.BASE64Encoder and guidelines to reduce the risk of depending on an unsupported sun.misc.Unsafe. The output suggests a replacement for the class in the JDK; but it’s much better if a language, frame- encoder, java.util.Base64, which was a new class in Java 8. work, or library can hide things that developers shouldn’t unsafe is a special case, because there is no suitable replace- use. To make sure your code isn’t using internal APIs that will ment for all of its functionality yet. be hidden in Java 9, you can use a tool called jdeps. JEP 260 talks about which internal APIs are going away Figure 2 shows where my compiled classes live in my and which will remain accessible. Java team member Mark project. Reinhold provided the following summary in an email to one Many tutorials suggest you use jdeps with a JAR file, but of the principal JDK mailing lists to explain how each API will you can also use it with your class files. For my application, be handled by the Java team:
Figure 2. Location of compiled classes in the project Figure 3. Output from running jdeps 18
ORACLE.COM/JAVAMAGAZINE //////////////////////////////////////////// JULY/AUGUST 2017 //java 9 /
■■ If it has a supported replacement in JDK 8, then we will uses, and determine whether they and the related parts of the encapsulate it in JDK 9. toolchain presently support running with Java 9. ■■ If it does not have a supported replacement in JDK 8, then we will not encapsulate it in JDK 9, so that it remains acces- Compiling with Java 9 sible to outside code. If you followed my previous advice, compiling with Java 9 ■■ If it has a supported replacement in JDK 9, then we will should be simple. In my code, if I compile with Java 9 without deprecate it in JDK 9 and encapsulate it, or possibly even fixing those errors identified in Figure 1 and Figure 3, I will get remove it, in JDK 10. the two errors I was expecting: one error stating I cannot use Compiler warnings and jdeps can show you areas in your code underscore as a field name and one that shows I can no longer that might be problematic in Java 9 and even suggest solu- access BASE64Encoder. Both of these are straightforward to tions. These problems can be fixed while you’re still run- fix. For the first, I rename the field. For the second, I import ning with an earlier version of Java (provided the suggested java.util.Base64 and replace the following old line of code: replacement classes are available in that version), and doing so will ease your transition to Java 9. String encodedString = new BASE64Encoder().encode(bytes); Running with Java 9 The migration guide I mentioned earlier suggests running with this: your application with Java 9 before recompiling or making any other changes. One place you might want to do this test- String encodedString = ing is in a continuous integration (CI) environment: you can Base64.getEncoder().encodeToString(bytes); use the artifacts built with your current version of Java but run the application and its tests The use of sun.misc.Unsafe won’t give me an error or warn- with Java 9. ing (at this point), because it’s still accessible in Java 9. See However, at the time of this Java 9 contains “Removed or Changed APIs” for more examples of changes writing, many of the common CI several changes that might affect your code. servers and some build tools, such The external libraries my application depends on all work as Gradle, do not yet fully support that might affect with Java 9, so after I apply the two fixes above, everything Java 9. If your project uses Maven, your application; compiles and runs as expected. However, you might find a few CI servers, such as TeamCity, some might not that some of the libraries you’re using aren’t compatible with will be able to compile or run your Java 9. There is a list of major open source libraries that have code with Java 9. But because the cause compilation been testing with Java 9. If you have a problem with a library, JDK and JRE were restructured as errors but instead you should check whether there is an updated version of the part of Java 9, some tools will need will demonstrate library that supports Java 9. to be updated to work correctly. You should find out which CI different behavior. Unexpected Behavior server and build tool your team Java 9 contains several changes that might affect your appli- 19
ORACLE.COM/JAVAMAGAZINE //////////////////////////////////////////// JULY/AUGUST 2017 //java 9 /
cation; some might not cause compilation errors but instead will demonstrate different behavior. The migration guide mentioned earlier covers these changes. Here’s a summary of some of the changes that might affect you. I’ve listed them as links with the associated JEP number, so you can look up any of them if they become suspects in what you perceive to be behavioral changes. ■■ JEP 231: Remove Launch-Time JRE Version Selection The Best Resource ■■ JEP 240: Remove the JVM TI hprof Agent ■■ JEP 241: Remove the jhat Tool for Modern Cloud Dev ■■ JEP 260: Encapsulate Most Internal APIs ■■ JEP 289: Deprecate the Applet API ■■ JEP 298: Remove Demos and Samples The Oracle Developer Gateway is the best place ■■ JEP 214: Remove GC Combinations Deprecated in JDK 8 to jump-start modern cloud development. With ■■ JEP 248: Make G1 the Default Garbage Collector free trials of PaaS and IaaS, documentation galore, ■■ JEP 271: Unified GC Logging piles of downloads, and tutorials for leveling up ■■ JEP 158: Unified JVM Logging your skills, it’s the resource of choice for developers ■■ JEP 223: New Version-String Scheme working in Java, mobile, enterprise apps, and more. ■■ JEP 245: Validate JVM Command-Line Flag Arguments
Conclusion Trials. Downloads. Tutorials. In this article, I have examined how to port Java 8 code to Start here: developer.oracle.com Java 9, without getting into the question of modularity. This explanation is intended for readers who want to use many of the innovations in Java 9 discussed here and in the accompa- nying article by Simon Ritter, “Nine New Developer Features in JDK 9.” [As this issue goes to press, modules have not been finalized by the Java Community Process, so coverage of working with modules will appear in a forthcoming issue of Java Magazine. —Ed.]
Trisha Gee is a Java Champion with expertise in Java high-per- developer.oracle.com formance systems. She is a leader of the Seville Java User Group (SVQJUG) and dabbles in open source development. Gee is the #developersrule IntelliJ IDEA developer advocate for JetBrains. 20
ORACLE.COM/JAVAMAGAZINE //////////////////////////////////////////// JULY/AUGUST 2017 //java 9 / Java 9 Core Library Updates: Collections and Streams Collections, Streams, and iterators have all added new capabilities.
ava 9 introduces many refinements to Java 8 fea List
Let’s face it: this is bulky for such a simple and common Again, this is fairly verbose. Note that some programming thing to do. We admit that this isn’t the only way to instan languages offer a feature to solve this problem by adding tiate a List though. Arrays.asList() has been around since collection literals to the programming language. This gives before Java 5, and it originally took just an array. In Java 5, it you some syntax that instantiates a collection from specific was converted to accept varargs and is in common use. values. Here’s an example in Groovy: 21
ORACLE.COM/JAVAMAGAZINE //////////////////////////////////////////// JULY/AUGUST 2017 //java 9 /
def values = ["Hello", "World", "from", "Java"] as Set reduce the scope for bugs related to referring to null values in collections. It also simplifies the internal implementation. One solution to implementing this is to provide some meth A bigger difference, compared to most collections in the ods that construct collections from values and then use a JDK, is that these collections are immutable. Immutability varargs constructor to make them syntactically shorter, simi reduces the scope for bugs by removing the ability for one lar to collection literals. This is the approach used in Java 9, part of an application to cause problems by modifying state so you can do the following, which is a lot more concise: that another component is relying on. Immutability is a con cept that has been advocated by functional programming for List
Map
ORACLE.COM/JAVAMAGAZINE //////////////////////////////////////////// JULY/AUGUST 2017 //java 9 /
} Stream.of("app.config", "app.home", "user.home") else .flatMap(key -> { Stream.ofNullable(System.getProperty(key))) return Stream.of(property); .findFirst() } .orElseThrow(IllegalStateException::new); }) .findFirst() takeWhile and dropWhile. Suppose you have an application that .orElseThrow(IllegalStateException::new); is processing payments being made on an ecommerce website and you’re maintaining a list of all payments for the current That’s a little ugly. What’s going on here? The code is look day that are sorted from the largest down to the smallest. ing up each property in the Stream and using the flatMap You have a business requirement to produce a report on every operation. flatMap is used here because it allows you to map payment that is £500 or greater at the end of the day. A natu an element to zero or one elements in the Stream. If you can ral way of writing this code using Java 8 Streams might be: look up the system property, a Stream is returned contain ing only it, but if you can’t look it up, an empty Stream is List
Even after this refactoring, however, the code reads slightly List
ORACLE.COM/JAVAMAGAZINE //////////////////////////////////////////// JULY/AUGUST 2017 //java 9 /
While filter retains all elements in the Stream that match 3 on every iteration. It then filters to ensure that the numbers its predicate, takeWhile stops once it has found an element are less than 100 and uses a method reference to print the that fails to match. The dropWhile operation does the inverse: resulting numbers. It looks straightforward, but if you run it, it throws away the elements at the start for which the predi you’ll find that there’s a big problem. Go on: try it! cate is false. That’s right: the program never terminates. It keeps So far, we’ve talked about streams that have a defined adding 3 in a loop infinitely. That’s because there’s no way order: an encounter order. The order of a stream can be defined to know in the filter that the numbers continue to increase. at its source. For example, if you’re streaming from a list of You can solve that problem with the new version of iterate values, the order in the list is the encounter order. It is also in Java 9, which takes a predicate as its second argument that possible to have Stream operations that introduce an encoun indicates at what point to stop iterating up. So, rewrite the ter order into their pipeline, for example, sorted(). Most, code as follows: but not all, of the practical use cases of takeWhile() and dropWhile() rely upon their input streams having a defined IntStream.iterate(3, x -> x < 100, x -> x + 3) encounter order. .forEach(System.out::println); One use case for applying takeWhile() on an unordered stream is if you want to be able to stop the Stream operation. It now stops running after it has printed the number 99. The For example, perhaps you have a Stream operation that may sample code here used the IntStream interface because it was operate on an infinite stream, processing all the data in it, but operating on primitive int values, but the iterate() methods you want to be able to stop the Stream when your application appear on both the primitive and regular Stream interfaces. shuts down or a user needs to cancel the stream pipeline. You Streams weren’t added on their own in Java 8; they came with can do this with a takeWhile() operation that reads from a a powerful Collectors class that has also been improved in piece of external state, such as a volatile boolean flag. When Java 9, as discussed next. you want to stop the stream pipeline, you simply set the state to false. Collectors iterate. A related update is the introduction of an alterna Collectors were another important addition to Java 8. Collec tive iterate() method for creating streams. The vintage tors let you specify data processing queries by aggregating iterate method from Java 8 takes an initial value and a func the elements of a Stream into various containers such as tion that provides the next value in the stream. Look at the Map, List, and Set. For example, you can create a map of the following example: sum of expenses for each year by using the groupingBy and summingLong collector from the Collectors class. In the rest of IntStream.iterate(3, x -> x + 3) this article, assume that there are static imports when a static .filter(x -> x < 100) method is referred to from the Collectors class. .forEach(System.out::println); Map
ORACLE.COM/JAVAMAGAZINE //////////////////////////////////////////// JULY/AUGUST 2017 //java 9 /
summingLong(Expense::getAmount)); private final String content;
So what’s new in Java 9? In Java 9, two new Collectors have public Tag(String content) { been added to the Collectors utility class: Collectors this.content = content; .filtering and Collectors.flatMapping. } We will show you how to use the new filtering and flat } Mapping functionality with a running example used through out the rest of the article. Here are the Expense and Tag class Collectors.filtering.Let’s revisit the example at the start of the definitions we use. “Collectors” section and say that you now need to build a map of the list of expenses for each year but only for expenses that public class Expense { are higher than £1,000. private final long amount; From the immediately preceding discussion, you already private final int year; know how to generate a Map of the list of expenses for each private final List
public Expense(long amount, int year, Map
ORACLE.COM/JAVAMAGAZINE //////////////////////////////////////////// JULY/AUGUST 2017 //java 9 /
criteria in a given year and thus return an empty list. Expense::getYear, flatMapping(expense -> Map
flatMapping. The flatMapping collector is the big brother of Conclusion the mapping collector. Let’s say you need to produce a map Java 9 adds new goodies to improve patterns by introducing of years with a set of tags from the expenses for each year. In new operations to Collections, Streams, and Collectors. These other words, you need to produce Map
ORACLE.COM/JAVAMAGAZINE //////////////////////////////////////////// JULY/AUGUST 2017
//java 9 / JShell: Read-Evaluate-Print Loop for the Java Platform Testing code snippets is now part of the JDK. CONSTANTIN DRABO
Shell, a new read-evaluate-print loop (REPL), will be latest Early Access preview build for JDK 9 for your environ- Jintroduced in JDK 9. Motivated by project Kulla (JEP 222), ment. Then, set your JAVA_HOME environment variable JShell is intended to provide developers an API and an interac- and run java -version to verify your installation. The out- tive tool that evaluates declarations, statements, and expres- put of the command should show something similar to the sions of the Java programming language. following: In this article, I present a brief overview of JShell, explain its use, and demonstrate its benefits for developers. java version "9-ea" Java(TM) SE Runtime Environment (build 9-ea+173) Overview Java HotSpot(TM) 64-Bit Server VM... JShell is a new tool in JDK 9 that offers a basic shell for Java that uses a command-line interface. It is also the first official To run JShell, type jshell at the command line: REPL implementation for the Java platform, even though this concept has existed in many languages (for example, Groovy [pandaconstantin@localhost ~]$ jshell and Lisp) and in Java third-party tools (such as Java REPL and | Welcome to JShell -- Version 9-ea BeanShell). So, it is not a new language, nor is it an IDE or a | For an introduction type /help intro new compiler for Java. JShell acts like a UNIX shell: it reads the instructions, When the prompt is available, you can get help on several evaluates them, prints the result of the instructions, and then useful commands by typing /help at the command line. displays a prompt while waiting for new commands. It is built Figure 1 shows the partial output from that command, with around several core concepts—snippets, state, wrapping, many of the principal commands explained succinctly. instruction modification, forward references, and snippet To understand how JShell works, let’s look at a few code dependencies—that I’ll explain. snippets. A snippet is an instruction that uses standard Java syntax. It represents a single expression, statement, or decla- How to Run JShell ration. The following is a simple snippet. The text below the In order to run JShell, you need to download and install the command is JShell output: 28
ORACLE.COM/JAVAMAGAZINE //////////////////////////////////////////// JULY/AUGUST 2017 //java 9 /
System.out.println("My JShell snippet"); x ==> 0 My JShell snippet y ==> 0 int sum ==> 0 (In my examples in this article, the characters in blue indicate text entered at the command line into JShell, and the result- x = 10 ; y = 20 ; sum = x + y; ing output is shown in black monospace.) x ==> 10 Like Java code, JShell allows you to declare variables, y ==> 20 methods, and classes: sum ==> 30
int x, y, sum System.out.println("Sum of " + x + " and " + y + " = " + sum); Sum of 10 and 20 = 30 /list [
History of what you have typed public String getClassRoom() { /! return classRoom ; Re-run last snippet } Figure 1. Partial list of JShell commands 29
ORACLE.COM/JAVAMAGAZINE //////////////////////////////////////////// JULY/AUGUST 2017 //java 9 /
public void setClassRoom(String classRoom) { mined by results of the eval() method of the JShell instance, this.classRoom = classRoom ; which evaluates code. There are seven status states: } ■■ DROPPED: The snippet is inactive. ■■ NONEXISTENT: The snippet is inactive because it does not public double getGrade() { yet exist. return grade ; ■■ OVERWRITTEN: The snippet is inactive because it has been } replaced by a new snippet. ■■ RECOVERABLE_DEFINED: The snippet is a declaration public void setGrade(double grade) { snippet with potentially recoverable unresolved references this.grade = grade ; or other issues in its body. } ■■ RECOVERABLE_NOT_DEFINED: The snippet is a declara- tion snippet with potentially recoverable unresolved refer- } ences or other issues. (I discuss the difference between this created class Student and the previous state shortly.) ■■ REJECTED: The snippet is inactive because it failed com- The indentation looks different than in Java, because this code pilation upon initial evaluation and it is not capable of was typed at the JShell command line. Some normal Java state- becoming valid with further changes to the JShell state. ments are not needed at this initial declaration. For example, ■■ VALID: The snippet is a valid snippet. JShell automatically imports many typical packages. In our When a snippet is not declared, it is considered inactive example, the following imports were done automatically: and not part of the state of the JShell instance nor is it vis- ible to the compilation of other snippets. At this stage, it is a import java.io.* NONEXISTENT snippet. import java.math.* If the snippet is submitted to the eval() method and import java.net.* there are no errors, it becomes part of the state of the JShell import java.nio.file.* instance and the status is VALID. Querying JShell gives import java.util.* isDefined == true and isActive == true. import java.util.concurrent.* In the case where the signature of the snippet is valid import java.util.function.* but the body contains issues or unresolved references, the import java.util.prefs.* status is RECOVERABLE_DEFINED and a JShell query states import java.util.regex.* isDefined == true and isActive == true. import java.util.stream.* If the signature of the snippet is wrong and the body also contains issues or unresolved references, the snippet’s At any given point, you can see the already imported pack- status is RECOVERABLE_NOT_DEFINED and the status is ages with the /import –all command listed earlier. isDefined = false even though the snippet stays active State. Each statement in JShell has a state. The state defines (isActive == true). the execution status of snippets and of variables. It is deter- A snippet becomes REJECTED when compilation fails, 30
ORACLE.COM/JAVAMAGAZINE //////////////////////////////////////////// JULY/AUGUST 2017 //java 9 /
and it is no longer a valid snippet. This is a final status and //Store the status of the snippet will not change again. At this stage, both isDefined and Snippet.Status snippetstatus = isActive are false. You can also deactivate and remove a shell.status(snippet); snippet from the JShell state with an explicit call to the if(snippetstatus == Status.VALID) { JShell.drop(jdk.jshell.PersistentSnippet) method. At System.out.println("Successful "); that point, the snippet status changes to DROPPED. This is } also a final status and will not change in the future. } Sometimes a snippet type declaration matches another } one. In this case, the previous snippet is inactive and it } is replaced by the new one. The status of the old snippet becomes OVERWRITTEN and the snippet is no longer visible The result of the execution of this code is to other snippets (isActive == false). OVERWRITTEN is also a final status. Successful Successful Using JShell from a Program Successful The JDK offers APIs to developers to access JShell program- matically rather than by using the REPL. The code below cre- Wrapping ates an instance of JShell, evaluates a snippet, and provides You are not obliged to declare variables or define a method the status of the instructions. within a class. Classes, variables, methods, expressions, and statements evolve within a synthetic class (as an artificial import java.util.List; block). You can define them in the top-level context or within import jdk.jshell.*; a class body, as you wish. Also, if you’re a person who prefers import jdk.jshell.Snippet.Status; concision, you can at times skip using semicolons.
public class JShellStatusSample { String firstName , lastName public static void main(String... args) { firstName ==> null //Create a JShell instance lastName ==> null JShell shell = JShell.create(); //Evaluate the Java code String concatName(String firstName, List
ORACLE.COM/JAVAMAGAZINE //////////////////////////////////////////// JULY/AUGUST 2017 //java 9 /
cannot modify classes at the top level; however, as seen in String lastname; the following code, you can modify methods within classes. lastname ==> null
class Person { double grade; grade ==> 0.0 private String firstName ; private String lastName ; String getStudentFullName(String fn, String ln) { return fn + " " + ln ; } public String concatName(String firstName, | created method getStudentFullName(String,String) String lastName) { return firstName + lastName; firstname = "Wolfgang"; } firstname ==> "Wolfgang"
} lastname = "Mozart"; | created class Person firstname ==> "Mozart"
Because each statement or expression is created in its own System.out.println("Hello " + unique namespace, modifications can be applied at any time getStudentFullName(firstname,lastname)); without disturbing the overall functioning of the code. Hello Wolfgang Mozart
Forward References and Dependencies The output of the list command shows the following: Within the body of a class, you can refer to members that will be defined later. During evaluation of the code, the references 1 : String firstname ; produce errors. But because JShell works sequentially, the 2 : String lastname ; issue can be resolved by writing the missing member before 3 : double grade ; actually calling the snippets. 4 : String getStudentFullName When a snippet A depends on a second snippet B, any (String firstname, String lastname) { changes in snippet B are immediately propagated in A. Then, return firstname + " " + lastname ; if the dependent snippet is updated, the main snippet is also } updated. If the dependent snippet is invalid, the main snippet 5 : firstname = "Wolfgang" ; becomes invalid. 6 : lastname = "Mozart" ; If you declare variables and then initialize them, you can 7 : System.out.println("Hello" + see them by using the list command, for example: getStudentFullName(firstname,lastname));
String firstname; The numbers in the output are the snippet identifiers. They firstname ==> null are useful for manipulating a snippet (editing, dropping, 32
ORACLE.COM/JAVAMAGAZINE //////////////////////////////////////////// JULY/AUGUST 2017 //java 9 /
and so on). You can also list all the variables, methods, and classes that are in the code. Here’s an example of listing all the variables:
/vars | String firstname = "Wolfgang" | String lastname = "Mozart" | double grade = 0.0 Figure 2. The built-in snippet editor
If you decide to change the values of variables or edit a spe- /open StudentName.jsh cific snippet, you run /edit with the snippet identifier, Hello Wolfgang Mozart for example: Hello Constantin Drabo
/edit 6 JShell also offers some keyboard shortcuts. You can obtain the navigation history by using the up and down arrow keys. And A dialog box, as shown in Figure 2, appears to allow you to you can use the tab key to show you the options you have for modify the value. the text you’ve typed so far—a kind of IntelliSense feature. If I use the editor to change lastname to my last name, I get the following result response: Conclusion JShell has many possible uses. The first is for beginners to try lastname ==> "Drabo" out Java code without having to write a full program. In this sense, it is a terrific learning tool. It’s also a great tool for try- If I change the firstname to my first name, then I can rerun ing out small functions, validating that a web service is avail- the print-out function by simply referring to the snippet able and seeing what it returns, and so on. In addition, it’s an identifier, in this case, #7: excellent tool for trying out some quick layouts in JavaFX. Whether it is used from the command line or program- /7 matically, JShell is likely to become one of the most widely System.out.println("Hello" + used features of JDK 9. getStudentFullName(firstname, lastname)); Hello Constantin Drabo Constantin Drabo is a software engineer living in Burkina Faso. He is a NetBeans Dream Teamer and a Fedora Ambassador for You can use the /save command to save your snippets to the Fedora Project. Drabo is also the founder of FasoJUG, the first a file, and the /open command allows you to open and run Java user group in Burkina Faso (the former Upper Volta). the file: [This article is a substantially updated version of the JShell 9 /save StudentName.jsh tutorial that appeared in the July/August 2016 issue. —Ed.] 33
ORACLE.COM/JAVAMAGAZINE //////////////////////////////////////////// JULY/AUGUST 2017 //java 9 / Nashorn JavaScript Engine in JDK 9 Handy additions and support for ES6 make Nashorn even more useful.
JIM LASKEY ashorn, the JDK’s built-in JavaScript engine, has under- Nashorn continues to have broad usage, but its use Ngone a variety of improvements in this new release. appears to have settled into three main areas: Before diving into those enhancements, let me briefly set the ■■ The development of JavaScript applications that can be context for these changes so that their addition makes the run on both the client and the server. In the JavaScript most sense. world, this is known as isomorphic development. The advan- tages are huge for smaller shops that want to build front Background ends for both desktop and mobile services—a single pro- When I started the development of Nashorn in late 2010, I was gramming language with a common codebase and rapid just looking for a way to experiment with the newly minted delivery. Isomorphic development also scales well for invokedynamic (JSR 292) byte-code instruction. The JVM larger systems. team later adopted Nashorn as a test bed for invokedynamic, ■■ Runtime adaptive or dynamic coding. The term I like to use and the Nashorn Project drove much of the performance is soft coding, where portions of an application can be modi- improvements made to the invokedynamic implementation. fied after the application/server is deployed. This capability While this was going on, the Java group was discussing is used for everything from stored procedures in databases how JavaScript would likely grow to dominate client-side to application configuration management. development and that integrating JavaScript with Java would ■■ Shell scripting. This consists of using JavaScript in areas be a critical element of the client/server equation. Rhino—an where bash or Python would traditionally be used. open source implementation of JavaScript from the Mozilla There is often a lot of debate about Nashorn’s performance on Foundation that was then the JDK offering for JavaScript— the JVM compared to native JavaScript performance on plat- was getting long in the tooth, and further development was forms such as Google’s V8. Nashorn starts out slower because winding down. In November 2012, JDK Enhancement Proposal it translates the JavaScript to bytecode. After that, Nashorn is (JEP) 174, “Nashorn JavaScript Engine,” was approved, which at the mercy of HotSpot to deliver native code. This approach enabled work to begin in earnest to provide a fresh, robust, works well for long-running server applications but not as secure, full-featured implementation of ECMAScript-262 well for small and run-once scripts. The main reason we Edition 5.1 (ES5) to run on the Java platform. developed Nashorn in the first place was to run JavaScript Initially, Nashorn found a home in a wide variety of and Java together seamlessly. Most Nashorn applications do a applications, such as app servers, JavaFX applications, utili- great job of orchestrating JavaScript and Java, something that ties, shell scripts, embedded systems, and so on. V8 was not designed to do. 34
ORACLE.COM/JAVAMAGAZINE //////////////////////////////////////////// JULY/AUGUST 2017 //java 9 /
ES6 Support The first example creates a distinct symbol, which can be The most important issue for JavaScript developers doing used to create a property that is private to the current scope. isomorphic development is the need to have client/server The second example shows how symbols can be shared source code compatibility. With most browsers adopting (interned) across an entire context. ES6 uses shared symbols ECMAScript 6 (ES6) as the standard level of language sup- to define iterators and default toString functions. Symbol- port for JavaScript, it was essential to bring Nashorn in line. keyed properties are not exposed to any reflective operations. While the Nashorn team didn’t have time to deliver the com- New iterator protocol. ES6 provides a new protocol for iterating plete ES6 feature set for the JDK 9 release, more ES6 features over objects: will follow in future updates. To activate ES6 support, use --language=es6 on the command line. // assign an iterator function to the New keywords. Here is what you’ll find initially: the imple- // Symbol.iterator property mentation of the new keywords, let and const, follow ES6 myobj[Symbol.iterator] = function() { block scoping, with const creating an immutable local. For return { backward compatibility, var retains its ES5.1 semantics: next: function() { ... } } const a = 10; }; a = 20; // TypeError trying to set a constant // Iterate over myobj using a for..of statement for (let id of myobj) { let x = 10; print(myobj[id]); { } let x = 20; // different scope print(x); // prints 20 Note the introduction of for..of loops. Nashorn’s syntax } for each will still be available, but the team recommends print(x); // prints 10 from the outer scope switching to for..of even though they are functionally equivalent. Support for symbols. Symbols are string-like objects intro- New collections. New collection classes were added in ES6 and duced in ES6. They are primitives that are compared by ref- in Nashorn: Map and Set. These collection classes implement erence instead of by value. This makes every symbol unique, the new iterator protocol. which enables developers to create private object properties. let map = new Map(); // a new, unique symbol map.set('foo', 'bar'); let unique = Symbol('optionalName'); map.get('foo'); // -> 'bar' myobj[unique] = 'foo'; map.clear(); // a shared symbol for the given name map.get('foo'); // -> undefined let shared = Symbol.for('name'); myobj[shared] = 3; The weak reference versions of Map and Set have also been 35
ORACLE.COM/JAVAMAGAZINE //////////////////////////////////////////// JULY/AUGUST 2017 //java 9 /
implemented; WeakMap and WeakSet. An entry in one of these // Sample script containing an ES6 class declaration collections is removed by the garbage collector when the entry var script = "class XYZ {}"; value is no longer referenced by any other variable or object. Templates. Templates are a new form of string literals using // Parse the script and build an abstract syntax tree back-ticks as delimiters, which allow embedded expressions var json = parse(script); and multiline strings. Nashorn also supports ES6 “tagged” strings rendered by a function. // Convert the abstract syntax tree to JSON and print print(JSON.stringify(json, undefined, 4)); // Multiline string 'string text line 1 The result is the following JSON output: string text line 2' // Embedded expression { 'string text ${expression} string text' "type":"Program", // Rendered by function "tag" "body":[ tag 'string text ${expression} string text' { "type":"VariableDeclaration", Note that in –scripting mode, back-ticks are still used for "declarations":[ $EXEC expressions. { Binary and octal numbers. Finally, there is a new syntax for "type":"VariableDeclarator", binary and octal number literals. "id":{ "type":"Identifier", // Binary number literal "name":"XYZ" 0b111110111 === 503 }, // Octal number literal "init":{ 0o767 === 503 } In addition to these features from ES6, new capabilities } enhance Nashorn’s usefulness. ] } JavaScript Parsing API ] In JDK 9, Nashorn’s Parser API has been expanded to include } full ES6 syntax support. The following example shows how to parse a JavaScript sample: The Parsing API can also be used to analyze code or inject instrumentation, and so offers a developer lots of flexibil- // load parser.js from Nashorn resources ity. NetBeans uses this API to handle most of its JavaScript //// Load the parser library functionality. 36
ORACLE.COM/JAVAMAGAZINE //////////////////////////////////////////// JULY/AUGUST 2017 //java 9 /
$EXEC 2.0 It is also possible to override stdin, stdout, and stderr by One of the most popular features of Nashorn is the ability passing input and output streams as the last three $EXEC to fork processes with a simple back-tick expression. This arguments. unusual capability enables developers to create shell scripts Multiple commands can be issued by using semicolons or written in JavaScript. new lines.
var listing = `ls –l`; $EXEC(< The $EXEC function now has a throwOnError property that, if $EXEC("setenv PATH ~/bin:${ENV.PATH}; mycmd"); set to true, will raise a RangeError if the command fails. It is $EXEC("cd ~/bin; ls -l"); still possible to check the $EXIT global to check the status of the command. jjs as a REPL The release of Nashorn with JDK 8 introduces a new $EXEC.throwOnError = true command-line tool: Java JavaScript (jjs). jjs made it easier `javac my.java` for developers to test out Nashorn features and to launch ORACLE.COM/JAVAMAGAZINE //////////////////////////////////////////// JULY/AUGUST 2017 //java 9 / //user groups / ■■ Ctrl-k to delete the rest of a line and Ctrl-y to restore the line THE LONDON JUG ■■ Up and down arrows to scroll through the input history ■■ Tab completion to expand globals, properties, and Java types The London Java Com ■■ VT100 escape sequences to format the screen munity (LJC), also known With all these small changes, life is made a little bit easier. as the LJC JUG (@ljcjug), comprises developers in Performance Europe and in the interna- In JDK 9, optimistic type optimization is on by default, which tional scene. The LJC was means that, over time, the performance of code on Nashorn created in 2006 when Barry improves as stronger typing is determined by the engine. Cranford from the London Java recruitment firm function f(array, i) { RecWorks sought to bring return array[i] + array[i + 1]; together like-minded Java } developers for sharing knowledge and skills. Since then, the LJC has grown to more than 6,000 members. In the example above, Nashorn will initially optimize the From the early days, the LJC had the good fortune to have function f assuming that i and the contents of array are leaders such as Zoe Slattery, Ben Evans, Martijn Verburg, integers (because of the plus sign.) If it turns out that these Simon Maple, John Stevenson, Trisha Gee, and many other assumptions are not correct, Nashorn will create a new edi- seasoned Java developers. tion of the function with the actual type used and hot-swap The LJC has been actively involved with the Java Com the old code with the newer version. This optimization is munity Process (JCP) and has won the 11th Duke’s Choice specialized per call site, so the best solution is always used. Award and co-won the JCP Member of the Year honor. With help and support from staff from RecWorks, the LJC Conclusion organizes three to four events every month. One of these is We’ve seen here that the Nashorn engine in JDK 9 provides a regular hack day called HackTheTower, where participants many convenient new features. This summary covers what’s gather in groups hacking on OpenJDK, doing projects in Scala new in this release, but the team has a lot more in the pipe- or Clojure or working independently on pet projects. The LJC line that it hopes to show you soon. also runs the annual Open Conference (UnConf) and supports Devoxx UK and Devoxx4Kids every year. These conferences Jim Laskey (@wickund) is a senior development manager in the involve close cooperation between the LJC and other JUGs in Java Platform group at Oracle. Laskey has been a compiler-runtime the UK, such as those in Bristol and Manchester, England. developer since the mid-1970s and has worked at Symantec, In addition, LJC members share homegrown libraries and Apple, and Azul Systems. frameworks, answer questions on the mailing list, and par- ticipate in JUG-organized projects such as Adopt-a-JSR and Adopt OpenJDK. If you think that sounds fun, join up! 38 ORACLE.COM/JAVAMAGAZINE //////////////////////////////////////////// JULY/AUGUST 2017 //java 9 / Working with the New HTTP/2 Client An incubating technology in JDK 9 promises to make HTTP communication a lot simpler. GASTÓN HILLAR ava 9 introduces a new HTTP client API defined in Java Presently, most configurations that support HTTP/2 JEnhancement Proposal (JEP) 110 that implements HTTP/2 provide support only for h2. Thus, it is very important to and WebSocket. This new HTTP client is included as an understand how to configure the client to work with modern incubator module, and its goal is to replace the legacy Http- versions of TLS. I include a complete example to cover this URLConnection API. In this article, I explain how to work important scenario. with the asynchronous API provided by the new incubator The combination of the new client with the upgrades HTTP client. Specifically, I show how to use the new HTTP in the TLS stack makes it possible to provide support for client API with JShell, the new read-eval-print loop (REPL) Application-Layer Protocol Negotiation (ALPN) and, therefore, included with JDK 9. the client can use this TLS extension to negotiate HTTP/2 I start with an introduction to this new client showing with fewer round-trips. Based on the configuration settings basic synchronous usage. Then, I move to the asynchronous you use for the HTTP client, it can negotiate the previously version and I use the client to perform a basic GET request; I explained upgrade from HTTP/1.1 to h2c or select HTTP/2 also work with HTTP/2 over TLS. This way, you can see how to (h2) from scratch. In addition, the client provides support for work with the new HTTP client to take advantage of the lan- WebSocket conformity with RFC 6455. In this example, I focus guage features that provide nonblocking behavior. on the HTTP features. The new incubator module is included in jdk.incubator A Modern HTTP Client .httpclient in JDK 9. It is very important to take into account Whenever it was necessary to use an HTTP client in Java, it that this incubator module will be moved to another mod- was a common practice to use third-party clients. The new ule in future JDK versions. In previous prerelease versions of incubator HTTP client is capable of working with HTTP/1.1 and the JDK, the module had a different name. You need to make HTTP/2. It is possible to work with HTTP/2 over TLS (known as sure you are running the latest JDK 9 version for the following h2) and HTTP/2 over TCP using cleartext (h2c). code samples to work as expected. The new client is capable of including an upgrade header I use JShell to make it easier to demonstrate the usage of field with the h2c token to request an upgrade from HTTP/1.1 this HTTP client without all the necessary specific configu- to HTTP/2 over TCP. If the server doesn’t support h2c, there rations for build systems or IDEs to work with JDK 9. When I won’t be an upgrade and everything will go on working with was writing this article, many IDEs and build systems were HTTP/1.1. h2c stands for “HTTP/2 cleartext” and, therefore, it still not 100 percent compatible with JDK 9, so you might see is important and easy to remember that h2c is not encrypted. unexpected issues. However, once the IDEs and build systems 39 ORACLE.COM/JAVAMAGAZINE //////////////////////////////////////////// JULY/AUGUST 2017 //java 9 / provide full compatibility with JDK 9, you can use the code ■■ HttpResponse: Represents an HTTP response samples in a Java application built with any IDE. The API provides builders to create instances and config- The following command launches JShell with the jdk ure the different pieces. These are static methods that start .incubator.httpclient module specified as a value for the with the prefix new. However, the API doesn’t provide build- --add-modules option. This way, JShell will resolve the jdk ers for the headers represented with the HTTPHeader class. .incubator.httpclient and you will be able to use it within the Unfortunately, the URI is still specified as a java.net.URI JShell session. If you have multiple JDK versions installed instance. Thus, if you need to use query parameters, it is nec- and you don’t have JDK 9 in your path, you need to run the essary to format or concatenate strings. command in the bin folder for JDK 9. In macOS or Linux, you The following lines build an HttpClient instance named might need to replace jshell with ./jshell. client by chaining many method calls after the call to the HttpClient.newBuilder method that creates a new HttpClient jshell --add-modules=jdk.incubator.httpclient builder. For example, the call to the followRedirects method with HttpClient.Redirect.ALWAYS as an argument specifies JShell doesn’t require you to use semicolons (;) at the end of that I want the client to always follow redirects. In this case, the statements. However, in order to make the code compat- I want to follow redirects because I want to perform an HTTP ible with the Java code for building real-life applications, I GET request to the following URI: http://www.oracle.com. I prefer to use semicolons. Enter the following import state- do not specify any desired HTTP version for the client; there- ment in JShell: fore, the client will be created as an HTTP/1.1 client that won’t request an upgrade to HTTP/2 in the request header. The import jdk.incubator.http.*; final chained call to the build method finishes the code for the builder. JShell includes many import statements by default. However, if you don’t work with JShell, you need to add the following HttpClient client = HttpClient.newBuilder() additional import statements for the sample code to work: .followRedirects(HttpClient.Redirect.ALWAYS) .build(); import java.lang.*; System.out.println(client.version()); import java.net.URI; URI uri = new URI("http://www.oracle.com"); import java.net.URISyntaxException; HttpRequest request = HttpRequest .newBuilder() The new module separates requests from responses. The .uri(uri) following are the principal classes with which I work in the .GET() sample code to perform HTTP operations: .build(); ■■ HttpClient: Represents an immutable HTTP client with a specific configuration and allows you to send requests and After the HttpClient instance is built, I print the result receive responses of calling the client.version() method. JShell displays ■■ HttpRequest: Represents an HTTP request HTTP_1_1 because I used the default configuration. Its default 40 ORACLE.COM/JAVAMAGAZINE //////////////////////////////////////////// JULY/AUGUST 2017 //java 9 / value is HttpClient.Version.HTTP_1_1, and it makes the .BodyProcessor instance. In this client work only with HTTP/1.1. case, HttpResponse.BodyHandler With just a few The next line of code creates a new URI instance using .asString() returns a body pro- lines of code in the URI to which I want to make the HTTP GET request, and it cessor that stores the response JShell, I was able saves it in uri. Then, the code builds an HttpRequest instance body as a String with the default named request by chaining many method calls after the call charset. After the HTTP GET to use the new HTTP to the HttpRequest.newBuilder method that creates a new request is successfully pro- client with a very basic HttpRequest builder. cessed, the send method returns configuration and its The call to the URI method with uri as an argument an HttpResponse ORACLE.COM/JAVAMAGAZINE //////////////////////////////////////////// JULY/AUGUST 2017 //java 9 / Working with Asynchronous Execution .build(); Before demonstrating the usage of the client to work with URI uri = new URI("http://www.oracle.com"); HTTP/2 and TLS, I’ll work with the asynchronous API. JShell HttpRequest request = HttpRequest includes many import statements by default. However, if you .newBuilder() don’t work with JShell, you need to add the following addi- .uri(uri) tional import statement for the next sample code to work: .GET() .build(); import java.util.concurrent.CompletableFuture; CompletableFuture ORACLE.COM/JAVAMAGAZINE //////////////////////////////////////////// JULY/AUGUST 2017 //java 9 / name chosen for the sslContext ified as values for the --class-path option. This way, JShell method is confusing, because For software will resolve the jdk.incubator.httpclient and load the spec- it makes you think that the development ified class files that allow us to work with the Bouncy Castle HttpClient will use the old and tasks, you will find libraries. Make sure you launch JShell in the path in which deprecated SSL instead of TLS to you saved the JAR files. If you don’t have jshell included in work with h2. It is important to the new HTTP/2 the path, you need to specify its full path: avoid confusion about the usage of client to be extremely “SSL” and the various names. The useful, especially jshell --add-modules=jdk.incubator.httpclient --class- sslContext method will configure path=bcpkix-jdk15on-157.jar;bcmail-jdk15on-157 a TLS context, not an SSL context. I when you need .jar;bcprov-jdk15on-157.jar work with TLS version 1.2 (TLSv1.2) to work with an in my next example. interactive REPL The following code contains all the import statements. I’m I also use the Bouncy Castle also including many import statements that JShell runs by libraries to make it easy to load such as JShell. default, to make it easy to run the code when you don’t use certificates. I end up generating JShell. Import statements that duplicate ones JShell brings in an SSLContext instance configured automatically do not generate errors. for TLSv1.2. These Bouncy Castle libraries are very popular when developers are working with import jdk.incubator.http.*; TLS in Java. Using them, I combine the new HTTP client import java.util.concurrent.CompletableFuture; with the usage of Bouncy Castle libraries to work with h2 in import java.lang.*; JShell. When I was in the process of writing this article, the import java.net.URI; latest version of the Bouncy Castle libraries was 1.57 and, import java.net.URISyntaxException; therefore, I use the names for the JAR files that include this import jdk.incubator.http.*; version number. import java.security.KeyFactory; I won’t be working with any specific build system. I will import java.security.KeyStore; continue to make the examples work with JShell. However, import java.security.KeyStoreException; you can easily use the code as a baseline to configure any import java.security.NoSuchAlgorithmException; build system to work with the Bouncy Castle libraries. import java.security.PrivateKey; Download the following JAR files from the Bouncy Castle import java.security.SecureRandom; site and save them in a folder: import java.security.Security; ■■ bcmail-jdk15on-157.jar import java.security.UnrecoverableKeyException; ■■ bcpkix-jdk15on-157.jar import java.security.cert.Certificate; ■■ bcprov-jdk15on-157.jar import java.security.cert.CertificateException; The following line launches JShell with the jdk.incubator import java.security.cert.CertificateFactory; .httpclient module specified as a value in the --add- import java.security.cert.X509Certificate; modules option and the previously enumerated JAR files spec- import java.security.spec.InvalidKeySpecException; 43 ORACLE.COM/JAVAMAGAZINE //////////////////////////////////////////// JULY/AUGUST 2017 //java 9 / import java.security.spec.PKCS8EncodedKeySpec; an instance of the java.net.ssl.KeyManagerFactory class, import java.io.File; which it then returns. import java.io.FileInputStream; ■■ createTrustManagerFactory: Takes a certificate authority import java.io.FileReader; certificate filename and calls the createX509Certificate import java.io.IOException; FromFile method. The code uses the X509Certificate import java.io.InputStream; instance, and creates and returns an instance of the java import javax.net.ssl.KeyManager; .net.ssl.TrustManagerFactory class. import javax.net.ssl.KeyManagerFactory; ■■ createAndInitTLS12Context: Takes a certificate author- import javax.net.ssl.SSLContext; ity certificate filename, a client certificate filename, import javax.net.ssl.SSLSocketFactory; and a client key filename, and creates and initializes an import javax.net.ssl.TrustManager; SSLContext instance with the desired TLS version (TLSv1.2). import javax.net.ssl.TrustManagerFactory; The code uses the BouncyCastleProvider and calls the import previously explained createKeyManagerFactory and org.bouncycastle.jce.provider.BouncyCastleProvider; createTrustManagerFactory methods. import org.bouncycastle.util.io.pem.PemObject; The certificatesPath variable in the following code declares import org.bouncycastle.util.io.pem.PemReader; a base path for the certificates that you need to run this example. You should replace the contents of this string with The TLSContextHelper class declares many static methods the path in which you have a certificate authority certificate that will allow me to work with TLSv1.2. It is about 150 lines, file, a client certificate file, and a client key file. You must use so you need to download it from Java Magazine’s download files that will be compatible with the HTTP request you are area. The methods of importance in this code are going to process. I use a Windows path, D:\JavaMagazine ■■ getKeyFactoryInstance: Returns a java.key.KeyFactory \http2, as an example. However, the code that defines the instance that converts public and private keys of the variables that specify the filenames for the certificate RSA algorithm. authority certificate, the client certificate, and the client key ■■ createX509CertificateFromFile: Takes a certificate file- are compatible with any platform in which you are running name, loads the file contents, generates an instance of the code, such as Linux, Oracle Solaris, or macOS. The code X509Certificate from the file, and returns the instance. calls String.join and uses java.io.File.separator to build ■■ createPrivateKeyFromPemFile: Takes a key filename in the the filenames by combining the previously explained path PEM format, loads the file contents, generates an instance with filenames. Make sure you replace ca.crt, server.crt, of java.Security.PrivateKey, and returns the instance. and server.key with the appropriate filenames. The last line ■■ createKeyManagerFactory: Takes a certificate filename, creates and initializes the SSLContext that I will use with the a client key filename, and a client key password; and HttpClient to work with h2. calls the createX509CertificateFromFile and create PrivateKeyFromPemFile methods. Subsequently, the code String certificatesPath = "D:\\JavaMagazine\\http2"; uses the instances returned by these methods to create String caCertificateFileName = 44 ORACLE.COM/JAVAMAGAZINE //////////////////////////////////////////// JULY/AUGUST 2017 //java 9 / String.join(java.io.File.separator, URI uri = certificatesPath, new URI("https://your-rest-api-url-for-get-method"); "ca.crt"); HttpRequest request = HttpRequest String clientCertificateFileName = .newBuilder() String.join(java.io.File.separator, .uri(uri) certificatesPath, .GET() "server.crt"); .build(); String clientKeyFileName = CompletableFuture ORACLE.COM/JAVAMAGAZINE //////////////////////////////////////////// JULY/AUGUST 2017 //java 9 / tional lines, the code performs an HTTP GET request with an } asynchronous execution, as done in the previous examples. }); However, in this case, if the REST API is compatible with HTTP/2 over TLSv1.2, the HttpClient will work with this pro- Conclusion tocol instead of HTTP/1.1. These simple examples demonstrated how to use the new incubator module HTTP/2 client with HTTP/2 over TLS in HttpClient client = HttpClient.newBuilder() JShell. The module provides many additional features that you .sslContext(sslContext) can also use from JShell and that make code easy to read. For .version(HttpClient.Version.HTTP_2) software development tasks, you will find the new HTTP/2 .followRedirects(HttpClient.Redirect.ALWAYS) client to be extremely useful, especially when you need to .build(); work with an interactive REPL such as JShell. However, the System.out.println(client.version()); current disadvantage is that the module is included as an URI uri = new URI("https://your-rest-api-url-for-get- incubator and is subject to change. Nonetheless, if you can method"); tolerate some API changes, the benefits of the new features HttpRequest request = HttpRequest justify exploring the technology. .newBuilder() .uri(uri) Gastón Hillar (@gastonhillar) has been working as a software .GET() architect with Java since its first release. He has twenty years of .build(); experience designing and developing software and is the author of CompletableFuture ORACLE.COM/JAVAMAGAZINE //////////////////////////////////////////// JULY/AUGUST 2017 //fix this / Quiz Yourself Intermediate and advanced test questions hese questions simulate the level of difficulty of two dif- cI = (ChildIF)oI; // line n1 SIMON ROBERTS Tferent certification tests. Those marked “intermediate” cC = (ChildCL)pC; // line n2 correspond to questions from the Oracle Certified Associate cC = (ChildCL)oC; // line n3 exam, which contains material for a preliminary level of cI = (ChildIF)oC; // line n4 certification. Questions marked “advanced” come from the 1Z0-809 Programmer II exam, which is the certification test Which is true? Choose one. for developers who have been certified at a basic level of Java 8 a. Line n1 and line n3 both fail to compile. programming knowledge and now are looking to demonstrate b. The casts are unnecessary in both line n1 and line n3. more-advanced expertise. c. Line n3 fails to compile. Let me re-emphasize that these questions rely on Java 8. d. The casts are unnecessary in both line n2 and line n4. I’ll begin covering Java 9 in a future column and will make e. Line n4 fails to compile. that transition quite clear when it occurs. Question 2 (intermediate). Given the following: Question 1 (intermediate). Given this code: class P { interface ParentIF {} private int value; interface ChildIF extends ParentIF {} // line n1 interface OtherIF {} public P(int v) { class ParentCL {} value = v; class ChildCL extends ParentCL {} } class OtherCL {} } and this code: class S extends P { ChildIF cI = null; private int value; ParentIF pI = null; // line n2 OtherIF oI = null; public S(int v, int u) { ChildCL cC = null; // line n3 ParentCL pC = null; value = u; OtherCL oC = null; } } 47 ORACLE.COM/JAVAMAGAZINE //////////////////////////////////////////// JULY/AUGUST 2017 //fix this / Which of these statements is true? Choose one. new Thread(() -> { a. The code compiles without errors. delay(); b. Adding the following at line n2 allows the code to while (hold[0]) compile without errors: public S(int v) {}. ; c. Adding the following at line n3 allows the code to System.out.println("value is " + x[0]); compile without errors: this(v);. }).start(); d. Adding the following at line n3 allows the code to } compile without errors: super(v);. e. Adding the following at line n1 allows the code to And, choosing from these behaviors: compile without errors: private P(){}. 1. The program prints value is 0. 2. The program prints value is 99. Question 3 (advanced). You are writing a program that needs 3. The JVM exits (the program stops). to respond to changes in a directory, such as a new version of 4. The JVM does not exit (the program does not stop). a file being written or a file being added or deleted. Which describes all the outcomes allowed by the specification? Which of these features from the standard Java SE APIs would Choose one. you use in addressing this requirement? Choose one. a. 2 and 3 a. java.nio.file.Path b. Neither 1 nor 2, and 3 b. java.nio.file.Files c. Either 1 or 2, and 3 c. java.nio.file.FileVisitor d. Either 2 and 3; or neither 1 nor 2, and 4 d. java.nio.channels.AsynchronousChannel e. 3 and either 1 or 2; or neither 1 nor 2, and 4 e. java.io.File Question 4 (advanced). Given the following code: public static void delay() { Answers try { Thread.sleep((int) (Math.random() * 10)); } catch (InterruptedException ie) {} } public static void main(String[] args) { int[] x = {0}; Question 1. The correct answer is option C. This question boolean[] hold = {true}; examines some aspects of assignment compatibility. new Thread(() -> { As a summary, the compiler recognizes three situations delay(); during an assignment. First, the expression on the right has x[0] = 99; an is-a relationship with the type of the expression being hold[0] = false; assigned to. The expression could be an exact instance or }).start(); an instance of a class that is a subclass of the class that’s 48 ORACLE.COM/JAVAMAGAZINE //////////////////////////////////////////// JULY/AUGUST 2017 //fix this / the target of the assignment, interface types, but what matters to the compiler is whether or it could be an implemen- If a constructor does it’s possible that the reference being cast might actually tation of the interface that’s not explicitly state implement the ChildIF interface. In general, such a cast to an the target of the assignment. how to pass control interface type is plausible. For example, imagine this addi- In this situation, the assign- tional class definition exists: ment works directly and no cast to a superclass is necessary. constructor, the class BothImpl implements ChildIF, OtherIF {} The second situation is compiler implicitly where the expression on the Now suppose the variable oI refers to an instance of BothImpl. right might refer to something generates code in the That’s possible, because BothImpl has an is-a relationship to that is assignment-compatible, constructor that invokes OtherIF. In that case, the cast would succeed when executed. but it’s not definite. This hap- the zero-argument Because a scenario is possible in which the cast would suc- pens, for example, when the ceed, the compiler allows the code, deferring to the runtime expression on the left is a constructor of the system to determine if it actually works. This tells you that subclass of the expression on parent class. option A is false, because line n1 compiles (even though I’ve the right. It also happens in not discussed line n3 yet). many situations where inter- The code in line n2 takes a reference of ParentCL type faces are involved. In the lat- and casts it to ChildCL. This is always plausible, simply ter case, the compiler allows the assignment only if a cast is because the ChildCL type is assignment-compatible with the used, and it lets the runtime system verify the validity of the ParentCL type. Because you can assign pC = cC without any actual usage. cast, this means that the opposite, cC = (ChildCL) pC, while The third situation is where the compiler can prove that needing the cast, is definitely plausible, because you’d simply the assignment cannot possibly work, such as with classes be putting the original value back into cC. Therefore, line n2 that don’t share any class hierarchy. In this situation, the is definitely compilable, even though it doesn’t move the compiler rejects the assignment even if a cast is used. search for the right answers forward—option D was already None of the options in this question assigns from some- rejected, because the cast is necessary. thing that has an is-a relationship to a more general type in Line n3 attempts to cast a reference to an instance of the way that does not require a cast. Therefore, if any of the OtherCL to a ChildCL. This is not plausible. A simple instance casts is removed, what’s left is not a compilable assignment. of OtherCL is an OtherCL and is an Object but, because Java Because of this, options B and D are both incorrect. doesn’t permit multiple class inheritance, it’s not possible to Given that every case has an explicit cast, all that have any object that has both OtherCL and ChildCL as par- remains is to determine whether the assignment is plausible ents. Because of this, line n3 does not compile and option C and, therefore, whether it will be permitted by the compiler. is correct. Let’s look at these one at a time. Line n4 takes a reference to OtherCL and casts it to Line n1 takes a reference to an OtherIF and attempts to ChildIF. Similar to the consideration in line n1, this is plau- cast it to a ChildIF. There’s no relationship between these sible. Just imagine that you have another declaration: 49 ORACLE.COM/JAVAMAGAZINE //////////////////////////////////////////// JULY/AUGUST 2017 //fix this / class AnotherImpl extends OtherCL implements ChildIF {} In this example, the child class S—as written—has no explicit call to any constructor in the parent class P, so it will invoke Clearly it’s possible then to have the oC reference point at the zero-argument constructor of the parent. However, P has one of these objects, and that would successfully cast to the an explicit constructor that takes a single argument. Because ChildIF type as required. As a result, option E is incorrect. of this, the child constructor cannot compile, because it As a side note, if the definition of OtherCL were final, implicitly calls a (nonexistent) zero-argument constructor in guaranteeing there could be no subclasses of OtherCL, then P. Therefore, option A is false. line n4 would fail to compile, because no scenario like the one There are two likely solutions to the problem. Either outlined above would be possible. you provide the parent class P with a suitable zero-argument constructor to accept the child’s call, or you modify the child Question 2. The correct answer is option D. This question constructor to explicitly call the constructor that does exist investigates the initialization of parent class elements that in the parent class. It could call the existing constructor, or occurs as part of the initialization of subclasses. Java takes con- you could make another constructor in P with different argu- siderable pains to ensure that things are properly initialized. ments, and call that explicitly from S. None of the options (It’s not always possible to enforce that, but it’s a clear goal.) proposes that latter route, so you can ignore it. Three particular behaviors are relevant to this ques- Option B adds a single-argument constructor to the tion. First, any time a subclass is instantiated, it must call up child, but that doesn’t actually help. The provided construc- to a specific parent class constructor, passing the required tor still has no explicit constructor call; therefore, a zero- arguments, so that the parent has a chance to be properly argument constructor is still required in the parent. Adding initialized. such a constructor to the child does not help this situation. Second, in the unique situation that the source code for Note that mere matching of constructor signatures—that is, a class does not define any explicit constructor, the compiler matching the argument lists—has no value here. Therefore, creates one by default. That constructor takes zero arguments, option B is false. and it calls the zero-argument constructor of its parent class, Option C is actually valid syntax, but it is incorrect for the superclass, even if that class is Object. solving the problem at hand. The use of this(v); would try Third, if a constructor does not explicitly state how to to delegate to a constructor that takes one argument, but that pass control to a superclass constructor, the compiler implic- target constructor would have to be in the same class, not the itly generates code in that constructor that invokes the zero- parent. Because of this, option C is false. Also, note that con- argument constructor of the parent class. This rule means structors, unlike instance methods, are not inherited, so there that the constructor shown for S is equivalent to this: really is no target for the call proposed here. Option D is the correct syntax for invoking the single- public S(int v, int u) { argument parent class constructor. It satisfies the need for super(); the single argument by passing the value of v up to the parent value = u; class constructor. From there, that value will be stored in the } private member variable value that is a member of P. Because 50 ORACLE.COM/JAVAMAGAZINE //////////////////////////////////////////// JULY/AUGUST 2017 //fix this / of this, option D results in suc- Question 3. The correct answer is option A. This is almost one cessful compilation, and it is the Programmers need of those troublesome “learn the API” questions, except that, correct answer. a mental model of in this question, you don’t have to learn method names; you Option E might look tempt- how a computer works just have to learn about the facilities the API can offer. That’s ing, creating a zero-argument actually not a waste of time, because failing to learn such constructor in the parent, but that allows reasoning things often results in duplicating behavior that has already the constructor in this option is about their daily work. been provided for you. On that basis, I make no apology for private. A private zero-argument this question. constructor would not be acces So, what do these various features do? First, the sible to the child class and, for java.nio.file.Path interface is the modern way for a Java this reason, it does not solve the essential problem: the program to represent “path and filename” as they relate to construc tor in S tries to call a zero-argument constructor in P. disk storage. This formerly was done using the java.io.File S must have access to the target constructor, and the private class, but that class lacked expressive power for representing form fails in that respect. Because of this, option E is incor- less-universal features of file systems, such as permissions. rect. A private constructor might seem strange, but it can be Notably, Path is an interface, allowing entirely independent very useful for taking control of how objects are created, for implementations on different operating systems or even file example, in implementing the singleton, static factories, and system types, whereas File is a class, which made such flex- builder patterns. ibility harder to achieve. Along with many handy and predi- It’s also interesting to consider the private fields called cable features for interacting with the path segments, and for value that exist in both P and S. Is this a really bad idea? Are dealing with relative and absolute paths, the Path interface they actually the same field? In fact, neither is true. Because defines two methods called register, which allow code to the fields are private, there’s no naming collision; each is vis- determine easily when changes are made to a file system. ible only within the class that contains it. In effect, they’re Given this description, it’s clear that option A is the cor- not visible outside their classes, so nobody can be affected by rect answer. It’s also safe to infer that option E is incorrect, them, nor can the names collide with any other variable of because the File class is of limited functionality and it is that name. Also, they really do define separate fields; they’re considered to be a legacy feature. not somehow the same field. Therefore, while it might look The Files class is a container for static methods that per- odd when you are looking at both classes at once, this code form useful operations such as copying and moving files, cre- is actually fine and you wouldn’t even notice it if you didn’t ating and deleting files and directories, reading and manipu- see both pieces of source code at once. However, if these lating permissions, and traversing directory trees. The class fields were accessible outside the class—for example, if they also provides utility methods that can simplify access to the allowed default access—the code would be pretty horrible. data in files, for example, the lines method that reads a text Such a situation is typically called shadowing, or sometimes file as a Stream ORACLE.COM/JAVAMAGAZINE //////////////////////////////////////////// JULY/AUGUST 2017 //fix this / The FileVisitor interface is used with features such as significant simplification and can get you into trouble where the Files.walkFileTree method. The visitor is used to per- concurrency is concerned. Hardware engineers have some form operations on some or all of the files and directories in a radical tricks up their sleeve to make their processors per- directory tree. The interface can, therefore, examine the con- form faster, and Java needs to allow every host it runs on to tents of directories, but it does so on a one-time basis, and it use as many of these tricks as possible to ensure good per- is not directly suited to looking for changes. Therefore, option formance. Consequently, Java’s specification is not written C is incorrect. in terms of implementations but in terms of what memory The AsynchronousChannel interface is the base interface effects can be relied upon. The specification uses an idea from which some interesting classes are derived indirectly. called a happens-before relationship to allow reasoning about These interesting classes allow “callback” type asynchro- which data written by one thread must be visible to another nous I/O operations, which are potentially valuable in highly thread and when that data must be visible. concurrent systems that seek to minimize the number of Perhaps strangely, a happens-before relationship does threads they use. However, this capability has no direct rela- not actually say that one thing happens before another, at tionship with the issue of monitoring changes in a directory. least not in the sense you would expect. It does not really Therefore, option D is incorrect. relate to, nor does it actually mandate, execution order; it Finally, it’s fair to point out that although the Path inter- relates only to particular visibilities of an effect. That’s per- face defines the register method that facilitates monitor- haps surprising, but one rationale for this is that optimiz- ing changes on the file system, it’s not sufficient on its own. ing compilers have for decades indulged in the reordering of You’ll also need to pass an instance of WatchService to that instructions. Reordering can be safe in particular situations. method. You can get an instance of WatchService from a static Let’s look at a simple example: factory method: FileSystem.newWatchService(). double x = heavyComputation(); Question 4. The correct answer is option E. This question double y = otherComputation(); delves into one of the most commonly misunderstood areas if (x > 3) doSomethingWith(x); of Java’s specification—the memory model—and what it means for the behavior of threaded code. Two particular Notice that changing the order of the first two lines would points affect the behavior of the given program, and they make no difference to the result, but it’s possible that a com- are permitted by the specification: the visibility of writ- piler might generate more-efficient code as a result of this ten data and the perceived ordering of the write operations. reordering. It would be able to execute otherComputation Notice that one of these points is unlikely to be manifested if and store the result, and then perform heavyComputation you run the code, but that doesn’t mean the answer I give is and immediately use the value of x, rather than storing x incorrect; it just means your system doesn’t happen to behave and having to fetch it back again for the third operation. in this way. That might seem like a small improvement, but many small Programmers need a mental model of how a computer improvements can add up to a large improvement. works that allows reasoning about their daily work. Generally, What does a happens-before relationship tell us? If A the kind of model that serves well on a daily basis is a fairly happens before B, and B reads something written by A, the 52 ORACLE.COM/JAVAMAGAZINE //////////////////////////////////////////// JULY/AUGUST 2017 //fix this / happens-before relationship tells you that B will read the But, if it doesn’t see the boolean change, it never prints and value written by A. Importantly, unless both the happens- it doesn’t stop. That allows you to eliminate options A, B, and before relationship and the “observation” exist, no guar- C, all of which fail to acknowledge that the program might antees are given. Further, just because the happens-before never stop. relationship exists in one context (for example, between To evaluate the last two possibilities, you must con- two threads T1 and T2), that guarantees nothing about the sider the value that will be printed if the second thread sees visibilities of effects elsewhere where no such relationship the change in the boolean. You now know that it could cor- exists (for example, a third thread T3). As you would expect, rectly print either value is 0 or value is 99. Therefore, the happens-before relationship is created by the order of the option D, which suggests that if it stops, it must have printed code lines executed by a single thread, and happens-before value is 99, but admits that it might not stop at all, is incor- relationships are transitive. Therefore, if A happens before rect. Option E, which admits that it could either print a value B and B happens before C, then A happens before C. But and stop or print nothing and not stop, is the correct answer. that simple line-by-line expectation holds only for a single It’s likely the notion that “the specification allows this” thread, although the transitive effect is not limited to single is a bit unsatisfying, so let’s look at one way this might threads. Special steps must be taken to create any necessary actually happen in real hardware. But first, it’s important relationship across threads. to realize that trying to reason about Java memory behav- In the code example in the question, nothing is done to ior in terms of hardware implementation is dangerous and create any happens-before relationships between the two often misleading. The only reliable approach is to consider threads that are created and started inside the main method. the memory model and reason using that. Anyway, just to This means that the second thread—the one doing the quiet that nagging “but that could never happen” feeling, reading—might or might not see the change from 0 to 99 in here’s one possible way it might happen on real hardware. the array x. Similarly, it might or might not see the change First, suppose that both the threads created in the main from true to false in the array hold. It might see both method start running on their own CPUs, and those CPUs changes or it might see neither, but it also might see either have independent caches (which is not unreasonable). Now, one without seeing the other one. (That often comes as a sur- imagine that the writing thread runs, and it writes both 99 prise to the developer.) Therefore, the second thread might and false to its cache, not to main memory. Now, given that see the 99, yet not see the change to false, or it might see no happens-before relationship has been enforced between the change to true, but not see the change to 99. That second the threads, neither the underlying hardware nor the JVM possibility, which results in the program printing value is 0 has any obligation to maintain any kind of cache coherence and then exiting, is often a bit unexpected. (To be fair, it’s between those threads—and whether those values end up also a fairly unlikely result in typical computation hardware, in main memory or get moved to the other CPU’s cache is but the specification allows it, which means that this is a bug undefined. Therefore, imagine that the boolean value hap- in the code and that’s not OK.) pens to be flushed out of the cache, before the 99. (Caches Therefore, let’s consider the possible outcomes. What usually flush a row at a time, and these two data items might matters is what the second thread sees. If it sees the bool- happen to be in different rows. Then it would not be unrea- ean value change, it prints something and the program exits. sonable that they could be flushed in the opposite order from 53 ORACLE.COM/JAVAMAGAZINE //////////////////////////////////////////// JULY/AUGUST 2017 //fix this / the order in which they were written.) In this situation, write operations that were executed “in order” by one thread can be seen as occurring out of order by another thread. That is sufficient to explain why the memory model is the only safe way to reason about what does, and does not, constitute reli- able code in Java. It’s probably fair to discuss briefly how this code could be made to behave in the expected way. I venture to suggest Java Is Just that the expected behavior—that is, the behavior implied by the source code—is that it should print value is 99 and then stop. To achieve this, you must create a happens-before rela- the Beginning tionship between the write to hold[0] by the first thread and the read from it by the second thread. Your Java applications need high-performance One simple way to create a happens-before relationship and battle-tested platform and infrastructure between two threads depends on the fact that a write to a services to build, test, deploy, and monitor. volatile variable happens before a subsequent read from that Oracle Cloud delivers. same variable. It’s probably tempting, then, to modify the hold variable to be volatile. But that would not work, because Start with Java in the cloud—or choose whatever the modifier would relate to the variable, and that variable is language, database, compute service, and OS a reference to the array, not the storage in the array. In other option you need. Rapid scalability. True portability. words, you never write to the volatile variable itself. You It’s all here. Now. also cannot convert the array to a simple variable, because the access to the value from the nested Runnable instances mandates that the variable be effectively final. You could, Oracle Cloud. however, make hold into a simple static field in the enclos- Built for modern app dev. ing class and then label that static field as volatile. That’s not Built for you. the only way, of course, but it would be sufficient to solve this particular problem. Simon Roberts joined Sun Microsystems in time to teach Sun’s Start here: first Java classes in the UK. He created the Sun Certified Java developer.oracle.com Programmer and Sun Certified Java Developer exams. He wrote several Java certification guides and is currently a freelance edu- cator who teaches at many large companies in Silicon Valley and #developersrule around the world. He remains involved with Oracle’s Java certifica- tion projects. 54 ORACLE.COM/JAVAMAGAZINE //////////////////////////////////////////// JULY/AUGUST 2017 //contact us / magazine By and for the Java community Comments Finally, algorithms, unusual but useful Where? We welcome your comments, correc programming techniques, and most other Comments and article proposals should tions, opinions on topics we’ve covered, topics that hard-core Java programmers be sent to our editor, Andrew Binstock, and any other thoughts you feel impor would enjoy are of great interest to us, at [email protected]. tant to share with us or our readers. too. Please contact us with your ideas While it will have no influence on our Unless you specifically tell us that your at [email protected] and we’ll decision whether to publish your article correspondence is private, we reserve give you our thoughts on the topic and or letter, cookies and edible treats will the right to publish it in our Letters to send you our nifty writer guidelines, be gratefully accepted by our staff at the Editor section. which will give you more information Java Magazine, Oracle Corporation, on preparing an article. 500 Oracle Parkway, MS OPL 3A-3133, Article Proposals Redwood Shores, CA 94065, USA. We welcome article proposals on all Customer Service topics regarding Java and other JVM If you’re having trouble with your sub Subscription application languages, as well as the JVM itself. scription, please contact the folks at Download area for code and We also are interested in proposals for [email protected], who will do what- other items articles on Java utilities (either open ever they can to help. Java Magazine in Japanese source or those bundled with the JDK). 55 ORACLE.COM/JAVAMAGAZINE //////////////////////////////////////////// JULY/AUGUST 2017