Sei sulla pagina 1di 56

WHATS NEW IN NASHORN 34 | INCUBATING HTTP/2 39 | LANGUAGE QUIZ 47

JULY/AUGUST 2017

magazine
By and for the Java community

11
NINE NEW
17
MIGRATING
21
ENHANCEMENTS
28
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 Gastn 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.
11 iterators have
all added new
NINE NEW DEVELOPER capabilities.

FEATURES IN JDK 9
By Simon Ritter
Theres 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 16
06 Contact Us
common when community is valued.
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? Heres 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 Merchn
Senior Designer RESOURCES
Register Now
Arianna Pucherelli
Oracle Products

Oracle Code
Designer +1.800.367.8674 (US/Canada)
Jaime Ferrand
Oracle Services
Senior Publication Designer +1.888.283.0591 (US)
Sheila Brennan
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
java@omeda.com 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 intervieweeseven if they are Oracle employeesdo 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 Oracles
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

of Collaborative Work development. At the


Oracle Code roadshow,
expert developers lead
Delays in the delivery of major releases such as JDK 9 labs and sessions on PaaS,
are common when community is valued. Java, mobile, and more.

Get on the list


T his issue of Java Magazine is all about the
release of Java 9. When I was originally laying
out the editorial schedule, this special issue was
previous delays triggered a great sense of frustra-
tion. Not for me. Sure, I would have loved to have
the release and this magazine come out simulta-
for event updates:
go.oracle.com/oraclecoderoadshow

assigned to a slot in last years 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 inal
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.
patedwith excitementthat 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 diicult, 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 efort. 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 beneit president of development for the Java Platform
has long driven Javas 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 postJava 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 efort. 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 efects 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 Javas success. If youre a
ciic 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 Im trying to underscore how unique Oracles are a sacriice 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 iat. 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? ers view of Java community operations. Many deined 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 couldnt 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 javamag_us@oracle.com
open, consensual approach. (Im 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
Code, in which Josh Juneau presents a concise guide
By and for the Java community

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: JDEFERREDS DATABASE BEST PRACTICES

swallow means to catch the exception, do nothing download icon for Java Magazine when they accessed
ANNOTATIONS FOR ASYNC EVENT ACCESS WITH FOR LIBRARY
CLEANER CODE MANAGEMENT STREAMS DESIGN

ORACLE.COM/JAVAMAGAZINE

with it, and continue execution of the code. the new page. Downloading the PDF version of the
However, this is far from what Lombok is doing. magazine is a subscriber privilege. So you must log
MAY/JUNE 2017
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 dont need to explicitly han- subscriber-only beneit) and youll be asked to log in.
dle it in calling code, much like runtime exceptions. When you do so from a laptop or desktop, youll 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 ind the term swal- 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 javamag_us@oracle.com. 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
exceptionit 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 1621 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 2830
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 1821 thinkers building tomorrows
DENVER, COLORADO technology in ields 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 31AUGUST 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 1314, CONFERENCE SEPTEMBER 29OCTOBER 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 Fluf Just Stuf
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 ields of Java, micro- OReilly Software Architecture
OCTOBER 15 services, continuous delivery, Conference
SAN FRANCISCO, CALIFORNIA JAX London and DevOps. Conference ses- OCTOBER 1618, CONFERENCE
Whether you are a seasoned OCTOBER 912 sions, keynotes, and expo happen AND TUTORIALS
coder or a new Java programmer, LONDON, ENGLAND October 1011. Hands-on work- OCTOBER 1819, 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 ive 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 worlds leading innovators tices, and exceptional technical

PHOTOGRAPH BY MASSMATT/FLICKR 07
ORACLE.COM/JAVAMAGAZINE /////////////////////////////////////////// JULY/AUGUST 2017
//events /
skills. At this conference, youll cutting-edge Java and web devel-
hear about the best tools to use opment, software architecture,
and why, and the efect they can and innovative infrastructures.
have on your work. Youll learn Experts share their professional
strategies for meeting your com- experiences in sessions and work-
panys business goals, developing shops. This years 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 23 NOVEMBER 1315, CONFERENCE
SAN FRANCISCO, CALIFORNIA NOVEMBER 1617, WORKSHOPS October 15, 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 ofered #JavaOne
several Java tracks along with
Devoxx tracks related to web develop-
NOVEMBER 610 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. javamag_us@oracle.com. Other
ways to reach us appear on the
W-JAX last page of this issue.
NOVEMBER 610 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 Beginners 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

T
his single-topic issue of Java Magazine focuses on the beneits 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 inal 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- youre not using modules.
tion that might be wrong later, weve 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 inished and will ship bundled with this release. Our
whenever modules are oicially 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 youd
and enjoyable. Simon Ritters 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
Theres a lot more to this release than modules.
SIMON RITTER

T he big new feature in JDK 9 is the Java Platform Module


System coupled with the introduction of the modular JDK.
However, there are plenty of other new features in JDK 9, and
myList.add(new Point(4, 4));
myList = Collections.unmodifiableList(myList);

in this article, I focus on nine that are of particular interest Its not terrible, admittedly, but to create an immutable list
to developers. Where applicable, Ive included the relevant of four Points required six lines of code. JDK 9 addresses this
JDK Enhancement Proposal (JEP) number so you can ind 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. Lets 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<Point> list =
The problem, until now, has been that Java doesnt pro- List.of(new Point(1, 1), new Point(2, 2),
vide a simple way to create a collection with predeined data. new Point(3, 3), new Point(4, 4));
If you want a collection to be structurally immutable (that is,
you cant add, delete, or change references to elements), you The code is now much simpler.
need to do more work. The rules that apply to the use of the diferent collections
Lets look at a simple example using JDK 8: also apply (as you would expect) when using these factory
methods. So, you cannot pass duplicate arguments when you
List<Point> myList = new ArrayList<>(); create a Set, nor can you pass duplicate keys when you create
myList.add(new Point(1, 1)); a Map. A null value cannot be used as a value for any collec-
myList.add(new Point(2, 2)); tion factory method. The Javadoc documentation provides full
PHOTOGRAPH BY BOB ADLER/
THE VERBATIM AGENCY myList.add(new Point(3, 3)); descriptions of how the methods may be called. [Collections
11
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).
JDK 9 adds four new methods to Optional:
Be careful when using either
of these methods when you have
develop and test Java
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): isied 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 dont 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
Its 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 ininite 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 efectively 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 ixed 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
state change the input caused.
in interfaces will knows how many elements it can pass to the processor at any
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 bufering 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-
tion, automatic addition of termi-
methods that will that delivers horizontal scalability by spinning up new ser-
vice instances to handle increased load).
nal semicolons when needed, and remain encapsulated JDK 9 includes a new class, Flow, that encloses several
conigurable predeined imports within the interface. interfaces: Flow.Processor, Flow.Subscriber, Flow
and deinitions. 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.
deined after the declaration (but The Subscription interface contains two methods:
this is still not dynamic typing: once the type is set, it cant 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 signiicant 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 irst 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 signiicant 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 bufer overlow 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
Efectively inal variables can be used in try-with-resources

without being reassigned. Currently, each resource that


represented by the compiler,
but it cannot be expressed to
and provides control of
is used must be assigned to a new variable, even if that the JVM using the class signa- native processes.
resource has already been deined 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 efectively inal) 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<String> myList = new ArrayList<>() {


// Overridden methods
In JDK 9, it becomes this: };

try (alreadyDefinedResource) ... A single underscore will no longer be valid as an identiier.


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 irst time), it was also logical to include ment and you dont 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 identiier.)
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 inal 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 signiicant. The other and methods of the java.util.concurrent.atomic package.
interesting aspect of this feature is that it is the irst 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 ine-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 dont 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 signiicant 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- Heres 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 iles 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 whove used ProcessBuilder ls = new ProcessBuilder()
C and C++, its efectively 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<Process> lsPipeWc = ProcessBuilder
to arrays.
Once you have a VarHandle,
as these, you should .startPipeline(asList(ls, wc));

you can execute low-level consider migrating The ProcessHandle interface identiies and provides control of
memory ordering operations on your development to native processes. It provides methods to retrieve information
the variable it references. This about a process, such as the process ID as well as any child
capability allows you to per-
this release ASAP. and descendant processes. Also, there is a static method that
form atomic operations, such as returns an Optional<ProcessHandle> for a given process ID.
15
ORACLE.COM/JAVAMAGAZINE /////////////////////////////////////////// JULY/AUGUST 2017
//java 9 / //java proposals of interest /
The subinterface ProcessHandle.Info provides a range
of process-speciic 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 processs 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 oicial documentation. Over the
Conclusion years, other heap proilers 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 youre 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. </article> 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 oferings are also available,
in 1996 and spent time working in both Java development and notably JProiler 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 ind
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
T his article shows the steps you take to run Java 8 code and
use some of the new features of Java 9 without migrating
to modules. I principally examine what you need to do to get
Compiler warnings. First, of course, you can look at any com-
piler warnings, because some of those will tell you about
potential problems (see Figure 1).
the code compiling and running. Im 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 youd 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, Im using build 9-ea+166). the code has a ield 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 dont 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. Ill 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 efort
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 /
ier name in Java 9 as part of JDK Enhancement Proposal (JEP) I navigate to the location of my class iles 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 identiier names that consist of lag. Im using Windows, so my command line is the fol-
only a single underscore, youll 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 identiier 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 its 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 shouldnt unsafe is a special case, because there is no suitable replace-
use. To make sure your code isnt 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 ile, but of the principal JDK mailing lists to explain how each API will
you can also use it with your class iles. 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 ixing those errors identiied 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 ield 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 ixed while youre still run- ix. For the irst, I rename the ield. 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 wont give me an error or warn-
with Java 9. ing (at this point), because its 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 that might afect your code.
servers and some build tools, such
several changes The external libraries my application depends on all work
as Gradle, do not yet fully support that might afect with Java 9, so after I apply the two ixes above, everything
Java 9. If your project uses Maven, your application; compiles and runs as expected. However, you might ind
a few CI servers, such as TeamCity,
will be able to compile or run your
some might not that some of the libraries youre using arent compatible with
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
to be updated to work correctly.
will demonstrate library that supports Java 9.

You should ind out which CI diferent behavior. Unexpected Behavior


server and build tool your team Java 9 contains several changes that might afect your appli-
19
ORACLE.COM/JAVAMAGAZINE /////////////////////////////////////////// JULY/AUGUST 2017
//java 9 /
cation; some might not cause compilation errors but instead
will demonstrate diferent behavior. The migration guide
mentioned earlier covers these changes. Heres a summary of
some of the changes that might afect you. Ive 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

JEP 240: Remove the JVM TI hprof Agent


The Best Resource
JEP 241: Remove the jhat Tool

JEP 260: Encapsulate Most Internal APIs


for Modern Cloud Dev
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: Uniied GC Logging piles of downloads, and tutorials for leveling up
JEP 158: Uniied JVM Logging your skills, its 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
inalized by the Java Community Process, so coverage of
working with modules will appear in a forthcoming issue of
Java Magazine. Ed.] </article>

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.

J ava 9 introduces many reinements to Java 8 fea-


tures, such as Streams, Collectors, Optional, and
CompletableFuture, as well as enhancements to the Collec-
List<String> values =
Arrays.asList("Java 9", "is", "here");

tions API. This article focuses on using the new features This is a helpful improvement. The List returned by Arrays
RAOUL-GABRIEL URMA in Collections, Streams, and Collectors. In the next .asList() is a little strange, however. If you try to add an
AND issue, we will focus on reliability using Optional and element to the List, itll throw an UnsupportedOperation
RICHARD WARBURTON CompletableFuture. Exception. You might think that is OKafter all, its a List
that cannot be mutated. Not so fast: its actually a list that
Collection Factories wraps an array. So the set() operation will modify the
Java 9 adds a set of new factory methods to the Collections backing array and, in fact, if you hold onto the array that is
Framework. Lets start by looking at the problem these wrapped, it can be modiied. If you want to create a Set or a
methods are trying to solve, by instantiating a list with a Queue, you are out of luck as well; theres no Arrays.asSet().
few String values: The normal way to solve this problem is to use the Collection
constructor overload:
List<String> values = new ArrayList<>();
values.add("Java 9"); Set<String> values =
values.add("is"); new HashSet<>(Arrays.asList(
values.add("here"); "Java 9", "is", "here"));

Lets 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 isnt the only way to instan- languages ofer 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 speciic
was converted to accept varargs and is in common use. values. Heres 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 simpliies the internal implementation.
One solution to implementing this is to provide some meth- A bigger diference, 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<String> list = a long time. Speaking of functional programming, lets look
List.of("Java 9", "is", "here"); at the updates to the Streams API in Java 9.
Set<String> set =
Set.of("Hello", "World", "from", "Java"); Streams
Streams were a great addition to Java 8. The code that devel-
Maps now also have similar factory methods. They work dif- opers write using streams tends to read a lot more like the
ferently because Maps have keys and values rather than a sin- problem they are trying to solve, and less code is usually
gle type of element. For up to 10 entries, Maps have overloaded required. Java 9 brings some small improvements to streams.
constructors that take pairs of keys and values. For example, ofNullable. The Stream interface has a pair of factory methods
you could build a map of people and their ages, like this: called of() that allow you to create streams from prespeciied
values: one is an overload for a single value, and the other
Map<String, Integer> nameToAge takes a varargs parameter. These are very useful when youre
= Map.of("Richard", 49, "Raoul", 47); trying to test streams code and when you want to just instan-
tiate a stream with a few values. Java 9 adds an ofNullable()
The varargs case for Maps is a little bit harder: you need to factory. Lets see how you might use this functionality.
have both keys and values, but in Java, methods cannot have Lets suppose youre trying to ind a location where
two varargs parameters. Therefore, the general case is han- you can put some coniguration iles in a Java application.
dled by taking a varargs method of Map.Entry<K, V> objects You want to use a couple of diferent properties: lets say
and adding a static entry() method that constructs them: app.config and app.home. Lets write this code in Java 8:

Map<String, Integer> nameToAge = String configurationDirectory =


Map.ofEntries(entry("Richard", 49), Stream.of("app.config", "app.home", "user.home")
entry("Raoul", 47)); .flatMap(key -> {
final String property =
The goal here isnt just to reduce verbosity; it is also to reduce System.getProperty(key);
the possibility of programmer errors. All the collections added if (property == null)
in recent years have banned the use of nulls as elements {
within collections, and these collections follow suit. This helps return Stream.empty();
22
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 youre maintaining a list of all payments for the current
Thats a little ugly. Whats 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 cant look it up, an empty Stream is List<Payment> expensivePayments = paymentsByValue
returned in its place, which results in no element being added .stream()
to the Stream. .filter(transaction ->
Unfortunately, a large statement-style lambda expres- transaction.getValue() >= 500)
sion with a null check is in the middle of the code. One alter- .collect(Collectors.toList());
native would be to use a ternary operator:
Unfortunately, the downside of this approach is that if you
String configurationDirectory = start processing many transactions in a day, the filter
Stream.of("app.config", "app.home", "user.home") operation is applied to every transaction in your input list.
.flatMap(key -> { You know that your input list is sorted by descending value
String prop = System.getProperty(key); of the transaction, so once you have found a transaction that
return prop == null ? Stream.empty() : fails your predicate, every transaction after that point can be
Stream.of(property); iltered out. If your list of transactions grew to be very large,
}) this would take an increasing amount of time to complete
.findFirst() and incur unnecessary ineiciency. Java 9 solves this problem
.orElseThrow(IllegalStateException::new); with the addition of the takeWhile operation.

Even after this refactoring, however, the code reads slightly List<Payment> expensivePayments = paymentsByValue
inelegantly. The Java 9 ofNullable would allow you to write .stream()
the same pattern much more succinctly and readably: .takeWhile(transaction ->
transaction.getValue() >= 500)
String configurationDirectory = .collect(Collectors.toList());
23
ORACLE.COM/JAVAMAGAZINE /////////////////////////////////////////// JULY/AUGUST 2017
//java 9 /
While filter retains all elements in the Stream that match 3 on every iteration. It then ilters 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- youll ind that theres a big problem. Go on: try it!
cate is false. Thats right: the program never terminates. It keeps
So far, weve talked about streams that have a deined adding 3 in a loop ininitely. Thats because theres no way
order: an encounter order. The order of a stream can be deined to know in the ilter that the numbers continue to increase.
at its source. For example, if youre 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 deined 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 ininite 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 werent 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 lag. 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<Integer, Long> yearToSum
This code prints all the numbers that are divisible by 3 and = purchases.stream()
less than 100. It starts with 3, which is divisible by 3, and adds .collect(groupingBy(Expense::getYear,
24
ORACLE.COM/JAVAMAGAZINE /////////////////////////////////////////// JULY/AUGUST 2017
//java 9 /
summingLong(Expense::getAmount)); private final String content;

So whats 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 iltering and lat- }
Mapping functionality with a running example used through-
out the rest of the article. Here are the Expense and Tag class Collectors.filtering. Lets revisit the example at the start of the
deinitions 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<Tag> tags; year, as follows:

public Expense(long amount, int year, Map<Integer, List<Expense>> yearToExpenses =


List<Tag> tags) { purchases.stream()
this.amount = amount; .collect(groupingBy(Expense::getYear));
this.year = year;
this.tags = tags; So, you could add a ilter to the streams, as follows:
}
Map<Integer, List<Expense>> yearToExpenses =
public long getAmount() { purchases.stream()
return amount; .filter(expense ->
} expense.getAmount() > 1_000)
.collect(groupingBy(Expense::getYear));
public int getYear() {
return year; Unfortunately, this means that if all the expense amounts for
} a certain year were below 1,000, the resulting map would not
contain an entry for that year (that is, no key and no value).
public List<Tag> getTags() { Instead, you can use the iltering collector, as follows,
return tags; which would preserve the year in the resulting Map and pro-
} duce an empty list. This would be a confusing thing in our
} report for a user to read. Is a given year missing because there
is some missing data, or is it simply a software bug? We want
public class Tag { to make it clear that there are no entries that meet their ilter
25
ORACLE.COM/JAVAMAGAZINE /////////////////////////////////////////// JULY/AUGUST 2017
//java 9 /
criteria in a given year and thus return an empty list. Expense::getYear,
flatMapping(expense ->
Map<Integer, List<Expense>> yearToExpensiveExpenses = expense.getTags().stream(),
purchases.stream() toSet())));
.collect(
groupingBy( Note that the flatMapping collector is related to the flatMap
Expense::getYear, method from the Stream API. That method takes a function
filtering(expense -> producing a Stream of zero or more elements for each ele-
expense.getAmount() > 1_000, ment in the input Stream. The result is then lattened into a
toList()))); single Stream.

flatMapping. The flatMapping collector is the big brother of Conclusion


the mapping collector. Lets 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<Integer, Set<Tag>>. additions help you write code that reads closer to the prob-
A irst attempt might look like this: lem statement and is easier to understand. Often when there
are major new releases, developers focus only on the lag-
expenses.stream() ship features, but in practice, many developer productivity
.collect( improvements can be found in the enhancement features of
groupingBy( recent releases. Java 8 was a fantastic release, and Java 9 now
Expense::getYear, makes some common patterns even simpler to use. </article>
mapping(Expense::getTags, toSet())));
Raoul-Gabriel Urma (@raoulUK) is the CEO and cofounder of
Unfortunately, this query will return a Map<Integer, Cambridge Spark, a leading learning community for data scientists
Set<List<Tag>>>. and developers in the UK. He is also chairman and cofounder of
By using flatMapping, you can latten the intermediate Cambridge Coding Academy, a community of young coders and
Lists into a single container. The flatMapping collector takes students. Urma is coauthor of the bestselling programming book
two arguments: a function from one element to a Stream of Java 8 in Action (Manning Publications, 2015). He holds a PhD in
elements and a downstream collector to collect the single
computer science from the University of Cambridge.
lattened stream into a container. With this, you can solve the
Richard Warburton (@richardwarburto) is a software engineer,
query, as follows:
teacher, author, and Java Champion. He is the author of the best-
selling Java 8 Lambdas (OReilly Media, 2014) and helps devel-
Map<Integer, Set<String>> = opers learn via Iteratr Learning and at Pluralsight. Warburton has
expenses.stream() delivered hundreds of talks and training courses. He holds a PhD
.collect( from the University of Warwick.
groupingBy(
26
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

J Shell, a new read-evaluate-print loop (REPL), will be


introduced in JDK 9. Motivated by project Kulla (JEP 222),
JShell is intended to provide developers an API and an interac-
latest Early Access preview build for JDK 9 for your environ-
ment. Then, set your JAVA_HOME environment variable
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 beneits 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 ofers a basic shell for Java
that uses a command-line interface. It is also the irst oicial 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 conceptssnippets, state, wrapping, many of the principal commands explained succinctly.
instruction modiication, forward references, and snippet To understand how JShell works, lets look at a few code
dependenciesthat Ill 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 [<name or id>|-all|-start]]
list the source you have typed
Heres an example of a valid class, which I use later:
/edit <name or id>
edit a source entry referenced by name or id
class Student {
/drop <name or id>
private String name ;
delete a source entry referenced by name or id
private String classRoom ;
/save [-all|-history|-start] <file>
Save snippet to a source file. private double grade ;
/open <file>
open a file as source input public Student() {
/vars [name or id|-all|-start]
list the declared variables and their values }
/methods [name or id|-all|-start]
list the declared methods and their signatures public String getName() {
/types [name or id|-all|-start] return name ;
list the declared types }
/imports
list the imported items public void setName(String name) {
/exit this.name = name ;
exit the jshell
}
/history
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 diference between this
created class Student and the previous state shortly.)
REJECTED: The snippet is inactive because it failed com-

The indentation looks diferent 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 snippets
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 deines (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 inal 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 inal 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 inal status. Successful
Successful
Using JShell from a Program Successful
The JDK ofers 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 deine a method
the status of the instructions. within a class. Classes, variables, methods, expressions, and
statements evolve within a synthetic class (as an artiicial
import java.util.List; block). You can deine them in the top-level context or within
import jdk.jshell.*; a class body, as you wish. Also, if youre 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<SnippetEvent> events = String lastName) {
shell.eval( "int x, y, sum; " + return firstName + lastName ;
"x = 15; y = 23; sum = x + y; " + }
"System.out.println(sum)" ); | created method concatName(String,String)
for(SnippetEvent event : events) {
//Create a snippet instance The following code shows the declaration of variables and a
Snippet snippet = event.snippet(); method in the top-level context. As discussed previously, you
31
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, modiications 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 deined 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 identiiers. 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. Heres 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
ciic snippet, you run /edit with the snippet identiier, Hello Wolfgang Mozart
for example: Hello Constantin Drabo

/edit 6 JShell also ofers 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 youve typed so fara 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 irst is for beginners to try
lastname ==> "Drabo" out Java code without having to write a full program. In this
sense, it is a terriic learning tool. Its also a great tool for try-
If I change the irstname to my irst 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, its an
identiier, 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. </article>
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 irst
a ile, and the /open command allows you to open and run Java user group in Burkina Faso (the former Upper Volta).
the ile:
[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
N ashorn, the JDKs built-in JavaScript engine, has under-
gone a variety of improvements in this new release.
Before diving into those enhancements, let me briely set the
Nashorn continues to have broad usage, but its use
appears to have settled into three main areas:
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 servicesa 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. ied 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 coniguration 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. Rhinoan where bash or Python would traditionally be used.
open source implementation of JavaScript from the Mozilla There is often a lot of debate about Nashorns performance on
Foundation that was then the JDK ofering for JavaScript the JVM compared to native JavaScript performance on plat-
was getting long in the tooth, and further development was forms such as Googles 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 irst 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 irst 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 deine iterators and default toString functions. Symbol-
port for JavaScript, it was essential to bring Nashorn in line. keyed properties are not exposed to any relective operations.
While the Nashorn team didnt 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 youll ind 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. Nashorns 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 Nashorns usefulness. ]
}
JavaScript Parsing API ]
In JDK 9, Nashorns 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 ofers a developer lots of lexibil-
// 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(<<EOD);


echo this ; echo that
In this example, listing will contain the output string from echo whatever you want
the ls l command. EOD
The back-tick expression is just shorthand for a call
to the function $EXEC. That is, `ls l` is shorthand Or, you can pipe the results of commands to the next com-
for $EXEC('ls -s'). mand using the vertical bar symbol.
$EXEC in JDK 9 is greatly improved over the previous
version. You can now pass in an array of strings for the irst $EXEC("echo 'my argument has spaces' | cat");
argument, which allows you to pass arguments containing
special characters, such as spaces. Finally, you can change the values of environment variables
on the ly with pseudo cd, setenv, and unsetenv built-in
$EXEC(["/bin/echo", "my.java", "your java"]); commands.

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
<shell>:1 RangeError: JavaScript applications without writing Java code.
$EXEC returned non-zero exit code: 2 With JDK 9, jjs has replaced its input and output API with
jline2, a new library for handling console input. This change
[The last two lines appear as a single line. Ed.] It is possible means that developers can use all the standard controls that
to better manage command I/O operations with standard are expected when they are using a shell:
redirection directives as command arguments. Left and right arrows to move through the input and an

option arrow to jump past symbols


$EXEC("echo 'my argument has spaces' > tmp.txt"); Forward and backward deletion capability

37
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
Up and down arrows to scroll through the input history
THE LONDON JUG
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 irm
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 Dukes 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 staf from RecWorks, the LJC
Conclusion organizes three to four events every month. One of these is
Weve 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 whats 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. </article> 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.

GASTN HILLAR
J ava 9 introduces a new HTTP client API deined in Java
Enhancement Proposal (JEP) 110 that implements HTTP/2
and WebSocket. This new HTTP client is included as an
Presently, most conigurations that support HTTP/2
provide support only for h2. Thus, it is very important to
understand how to conigure 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. Speciically, 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 coniguration 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 diferent 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
ield with the h2c token to request an upgrade from HTTP/1.1 this HTTP client without all the necessary speciic conigu-
to HTTP/2 over TCP. If the server doesnt support h2c, there rations for build systems or IDEs to work with JDK 9. When I
wont 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 conig-
The following command launches JShell with the jdk ure the diferent pieces. These are static methods that start
.incubator.httpclient module speciied as a value for the with the preix new. However, the API doesnt 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 speciied 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 dont 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 speciies
JShell doesnt 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 wont
request an upgrade to HTTP/2 in the request header. The
import jdk.incubator.http.*; inal chained call to the build method inishes the code for
the builder.
JShell includes many import statements by default. However,
if you dont 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

speciic coniguration 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 coniguration. 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
saves it in uri. Then, the code builds an HttpRequest instance
cessor that stores the response
body as a String with the default
JShell, I was able
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.
The call to the URI method with uri as an argument
cessed, the send method returns
an HttpResponse<String> that is
configuration and its
speciies the URI to which I want to make the request. Then, saved in response. synchronous API.
the chained GET method indicates that I want to make an The inal lines print the
HTTP GET request to the speciied URI. The inal chained call results of the statusCode() and
to the build method inishes the code for the builder. The body().length() methods that
code is very easy to read. The GET HTTP verb is clearly indi- provide the HTTP status code returned by the response and
cated as a method that I can easily recognize in the code that the length of the body retrieved as a String.
builds the HttpRequest instance. (These lines of code wont work in JShell if you enter
Then, the code shown next calls the client.send method them as they are displayed. It is necessary to enter each
that runs synchronously and blocks the execution until a statement in a single line. Unfortunately, when I was writing
response is retrieved. The code passes the previously created this article, JShell didnt allow entering code with multiple
HttpRequest instance, request, and HttpResponse.Body lines without throwing some unexpected errors. However,
Handler.asString() as arguments. putting all the code in a single line in this article would make
it very diicult to read.)
HttpResponse<String> response = The previous code retrieves the body for a web page with
client.send(request, an HTTP GET request to a String and uses HTTP/1.1. This is the
HttpResponse.BodyHandler.asString()); simplest usage you might have for the new HTTP client. If you
System.out.println( read the code again, you will notice that both the HttpClient
String.format("Status code: %d", and the HttpRequest are built in a similar way. The specii-
response.statusCode()); cation of the BodyHandler makes it easy to understand that
System.out.println( I want the HttpResponse as a String. You just need to think
String.format("Body length: %d", about working with builders and coniguring them based on
response.body().length()); your goals. The API is clear and chainable.
If you are used to modern Java code, you will ind the API
The second argument speciies the response body handler I very easy to use. With just a few lines of code in JShell, I was
want to use. A body handler takes the response status code able to use the new HTTP client with a very basic conigura-
and the response headers and returns an HttpResponse tion and its synchronous API.

41
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, Ill work with the asynchronous API. JShell HttpRequest request = HttpRequest
includes many import statements by default. However, if you .newBuilder()
dont 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<HttpResponse<String>> response =
client.sendAsync(request,
In the previous lines that worked with synchronous execu- HttpResponse.BodyHandler.asString());
tion, I called the client.send method. Now, I will write response.whenComplete((HttpResponse<String> response,
similar code to build the HttpRequest, and this time I Throwable exception) -> {
will call the client.sendAsync method that returns a if (exception == null) {
CompletableFuture<HttpResponse<String>>. This way, you System.out.println(
can take advantage of the support of dependent functions and String.format("Status code: %d",
actions that a java.util.concurrent.CompletableFuture<T> response.statusCode()));
triggers upon its completion and write code that uses the System.out.println(String.format(
HttpResponse<String>. [If youre not familiar with complet- "Body length: %d",
able futures, have a look at the explanation of them in Andrs response.body().length()));
Almirays article on JDeferred in the May/June 2017 issue of } else {
Java Magazine. Ed.] System.out.println(String.format(
In the following code, I call response.whenComplete to "Something went wrong. %s",
run code that prints the results of the statusCode() and exception.getMessage()));
body().length() methods that provide the HTTP status }
code returned by the response and the length of the body });
retrieved as a String, if no exception was thrown. Because
the asynchronous task generated under the hood can throw With just these few lines of code in JShell, I was able to use
an exception, I specify HttpResponse<String> response and the new HTTP client with a very basic coniguration and its
Throwable exception when I declare the lambda expres- asynchronous API.
sion that will be executed when the asynchronous task is
completed. In the lambda expression body, I work with the Working with HTTP/2 over TLS
response after making sure that the exception argument The HTTP client uses standard Java TLS mechanisms to
is null. enable work with HTTP/2 over TLS (h2). To do this program-
matically, it is necessary to create and initialize a javax.net
HttpClient client = HttpClient.newBuilder() .ssl.SSLContext instance and pass it as an argument to the
.followRedirects(HttpClient.Redirect.ALWAYS) sslContext method chained to the HttpClient builder. The
42
ORACLE.COM/JAVAMAGAZINE /////////////////////////////////////////// JULY/AUGUST 2017
//java 9 /
name chosen for the sslContext iied 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 iied class iles that allow us to work with the Bouncy Castle
HttpClient will use the old and libraries. Make sure you launch JShell in the path in which
deprecated SSL instead of TLS to
tasks, you will find you saved the JAR iles. If you dont 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 jshell --add-modules=jdk.incubator.httpclient --class-
sslContext method will conigure
useful, especially 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. The following code contains all the import statements. Im
I also use the Bouncy Castle
interactive REPL 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 dont use
certiicates. I end up generating JShell. Import statements that duplicate ones JShell brings in
an SSLContext instance conigured 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 iles that include this import jdk.incubator.http.*;
version number. import java.security.KeyFactory;
I wont be working with any speciic 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 conigure any import java.security.NoSuchAlgorithmException;
build system to work with the Bouncy Castle libraries. import java.security.PrivateKey;
Download the following JAR iles 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 speciied as a value in the --add- import java.security.cert.X509Certificate;
modules option and the previously enumerated JAR iles 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 certiicate authority

import java.io.FileReader; certiicate ilename and calls the createX509Certificate


import java.io.IOException; FromFile method. The code uses the X509Certiicate
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 certiicate author-

import javax.net.ssl.SSLContext; ity certiicate ilename, a client certiicate ilename,


import javax.net.ssl.SSLSocketFactory; and a client key ilename, 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 certiicates 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 certiicate authority certiicate
that will allow me to work with TLSv1.2. It is about 150 lines, ile, a client certiicate ile, and a client key ile. You must use
so you need to download it from Java Magazines download iles 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 deines the
instance that converts public and private keys of the variables that specify the ilenames for the certiicate
RSA algorithm. authority certiicate, the client certiicate, and the client key
createX509CertificateFromFile: Takes a certiicate ile- are compatible with any platform in which you are running
name, loads the ile contents, generates an instance of the code, such as Linux, Oracle Solaris, or macOS. The code
X509Certiicate from the ile, and returns the instance. calls String.join and uses java.io.File.separator to build
createPrivateKeyFromPemFile: Takes a key ilename in the the ilenames by combining the previously explained path
PEM format, loads the ile contents, generates an instance with ilenames. Make sure you replace ca.crt, server.crt,
of java.Security.PrivateKey, and returns the instance. and server.key with the appropriate ilenames. The last line
createKeyManagerFactory: Takes a certiicate ilename, creates and initializes the SSLContext that I will use with the
a client key ilename, 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<HttpResponse<String>> response =
String.join(java.io.File.separator, client.sendAsync(request,
certificatesPath, HttpResponse.BodyHandler.asString());
"server.key"); response.whenComplete((HttpResponse<String> response,
SSLContext sslContext = Throwable exception) -> {
SecurityHelper.createAndInitSSLContext( if (exception == null) {
caCertificateFileName, System.out.println(
clientCertificateFileName, String.format("Status code: %d",
clientKeyFileName); response.statusCode()));
System.out.println(String.format(
The following lines build an HttpClient instance named "Body length: %d",
client by chaining many method calls after the call to the response.body().length()));
HttpClient.newBuilder method that creates a new Http } else {
Client builder. Some parts of the code are similar to the System.out.println(String.format(
previous examples. However, in this case, notice that the "Something went wrong. %s",
call to the sslContext method (with the previously created exception.getMessage()));
SSLContext instance named sslContext as an argument) }
makes it possible to work with HTTP/2 over TLSv1.2. Then, the });
call to the version method with HttpClient.Version.HTTP_2
as an argument forces the use of HTTP/2, speciically, HTTP/2 After the HttpClient instance is built, the next line prints the
over TLSv1.2 because I chained the call to SSLContext, too. result of calling the client.version() method. JShell displays
HTTP_2 because I forced the usage of HTTP/2. In this case, you
HttpClient client = HttpClient.newBuilder() have to replace https://your-rest-api-url-for-get-method
.sslContext(sslContext) with the URI for your REST API that allows a GET method and
.version(HttpClient.Version.HTTP_2) provides a response with HTTP/2 over TLSv1.2. Remember
.followRedirects(HttpClient.Redirect.ALWAYS) that you are using certiicates, so any wrong certiicate will
.build(); make the TLS handshake (reported as an SSL handshake in
System.out.println(client.version()); the old Java names for exceptions) fail. With just a few addi-

45
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 ind 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 beneits of the new features
HttpRequest request = HttpRequest justify exploring the technology. </article>
.newBuilder()
.uri(uri) Gastn Hillar (@gastonhillar) has been working as a software
.GET() architect with Java since its irst release. He has twenty years of
.build(); experience designing and developing software and is the author of
CompletableFuture<HttpResponse<String>> response = many books related to software development, hardware, electron-
client.sendAsync(request, ics, and the Internet of Things. Hillar has been awarded the Intel
HttpResponse.BodyHandler.asString()); Black Belt Software Developer award eight times.
response.whenComplete((HttpResponse<String> response,
Throwable exception) -> {
if (exception == null) {
System.out.println(
String.format("Status code: %d", learn more
response.statusCode()));
System.out.println(String.format(
Home page for HTTP/2
"Body length: %d",
JEP 110: HTTP/2 Client (Incubator)
response.body().length()));
} else { JEP 222: jshell: The Java Shell
System.out.println(String.format( RFC 6455 (WebSocket Protocol)
"Something went wrong. %s", Bouncy Castle Crypto APIs
exception.getMessage()));
46
ORACLE.COM/JAVAMAGAZINE /////////////////////////////////////////// JULY/AUGUST 2017
//ix this /

Quiz Yourself
Intermediate and advanced test questions

SIMON ROBERTS T hese questions simulate the level of diiculty of two dif-
ferent certiication tests. Those marked intermediate
correspond to questions from the Oracle Certiied Associate
cI
cC
cC
=
=
=
(ChildIF)oI;
(ChildCL)pC;
(ChildCL)oC;
//
//
//
line
line
line
n1
n2
n3
exam, which contains material for a preliminary level of cI = (ChildIF)oC; // line n4
certiication. Questions marked advanced come from the
1Z0-809 Programmer II exam, which is the certiication test Which is true? Choose one.
for developers who have been certiied 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.
Ill 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
//ix 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 ile being written or a ile 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() {
try { Thread.sleep((int) (Math.random() * 10)); }
Answers
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 thats
48
ORACLE.COM/JAVAMAGAZINE /////////////////////////////////////////// JULY/AUGUST 2017
//ix 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 its possible that the reference being cast might actually
tation of the interface thats not explicitly state implement the ChildIF interface. In general, such a cast to an
the target of the assignment. interface type is plausible. For example, imagine this addi-
In this situation, the assign-
how to pass control tional class deinition exists:
ment works directly and no cast to a superclass
is necessary. constructor, the class BothImpl implements ChildIF, OtherIF {}
The second situation is
where the expression on the
compiler implicitly Now suppose the variable oI refers to an instance of BothImpl.
right might refer to something generates code in the Thats 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 its not deinite. This hap- Because a scenario is possible in which the cast would suc-
pens, for example, when the
the zero-argument 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 Ive
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 deinitely plausible, because youd simply
the assignment cannot possibly work, such as with classes be putting the original value back into cC. Therefore, line n2
that dont share any class hierarchy. In this situation, the is deinitely compilable, even though it doesnt move the
compiler rejects the assignment even if a cast is used. search for the right answers forwardoption 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, whats 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. doesnt permit multiple class inheritance, its 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.
Lets 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. Theres no relationship between these sible. Just imagine that you have another declaration:
49
ORACLE.COM/JAVAMAGAZINE /////////////////////////////////////////// JULY/AUGUST 2017
//ix this /
class AnotherImpl extends OtherCL implements ChildIF {} In this example, the child class Sas writtenhas no explicit
call to any constructor in the parent class P, so it will invoke
Clearly its 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 deinition 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 childs 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 diferent argu-
siderable pains to ensure that things are properly initialized. ments, and call that explicitly from S. None of the options
(Its not always possible to enforce that, but its 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 doesnt actually help. The provided construc-
to a speciic 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 signaturesthat is,
a class does not deine any explicit constructor, the compiler matching the argument listshas 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 satisies 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
//ix 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 dont have to learn method names; you
Option E might look tempt- just have to learn about the facilities the API can ofer. Thats
ing, creating a zero-argument
how a computer works 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 ilename as they relate to
constructor 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 ile 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 diferent operating systems or even ile
example, in implementing the singleton, static factories, and system types, whereas File is a class, which made such lex-
builder patterns. ibility harder to achieve. Along with many handy and predi-
Its also interesting to consider the private ields 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 ield? In fact, neither is true. Because deines two methods called register, which allow code to
the ields are private, theres no naming collision; each is vis- determine easily when changes are made to a ile system.
ible only within the class that contains it. In efect, theyre Given this description, its clear that option A is the cor-
not visible outside their classes, so nobody can be afected by rect answer. Its 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 deine separate ields; theyre considered to be a legacy feature.
not somehow the same ield. 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 iles, cre-
is actually ine and you wouldnt even notice it if you didnt ating and deleting iles and directories, reading and manipu-
see both pieces of source code at once. However, if these lating permissions, and traversing directory trees. The class
ields were accessible outside the classfor example, if they also provides utility methods that can simplify access to the
allowed default accessthe code would be pretty horrible. data in iles, for example, the lines method that reads a text
Such a situation is typically called shadowing, or sometimes ile as a Stream<String> directly. Although this is a very use-
variable hiding, and although its manageable with careful ful classwell worth looking at, if you havent alreadyits
syntax use, allowing it is just asking for maintenance trouble not directly suitable for solving the problem of watching for
and can cause all kinds of misunderstandings. change in a directory structure, and so option B is incorrect.
51
ORACLE.COM/JAVAMAGAZINE /////////////////////////////////////////// JULY/AUGUST 2017
//ix this /
The FileVisitor interface is used with features such as signiicant simpliication 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 iles 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, Javas speciication is not written
C is incorrect. in terms of implementations but in terms of what memory
The AsynchronousChannel interface is the base interface efects can be relied upon. The speciication 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, its fair to point out that although the Path inter- relates only to particular visibilities of an efect. Thats per-
face deines the register method that facilitates monitor- haps surprising, but one rationale for this is that optimiz-
ing changes on the ile system, its not suicient on its own. ing compilers have for decades indulged in the reordering of
Youll 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 Lets 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 Javas speciicationthe memory modeland what it
means for the behavior of threaded code. Two particular Notice that changing the order of the irst two lines would
points afect the behavior of the given program, and they make no diference to the result, but its possible that a com-
are permitted by the speciication: the visibility of writ- piler might generate more-eicient 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 doesnt mean the answer I give is and immediately use the value of x, rather than storing x
incorrect; it just means your system doesnt 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
//ix this /
happens-before relationship tells you that B will read the But, if it doesnt see the boolean change, it never prints and
value written by A. Importantly, unless both the happens- it doesnt 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 efects 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 Its likely the notion that the speciication allows this
thread, although the transitive efect is not limited to single is a bit unsatisfying, so lets look at one way this might
threads. Special steps must be taken to create any necessary actually happen in real hardware. But irst, its 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 threadthe one doing the quiet that nagging but that could never happen feeling,
readingmight or might not see the change from 0 to 99 in heres 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, its between those threadsand whether those values end up
also a fairly unlikely result in typical computation hardware, in main memory or get moved to the other CPUs cache is
but the speciication allows it, which means that this is a bug undeined. Therefore, imagine that the boolean value hap-
in the code and thats not OK.) pens to be lushed out of the cache, before the 99. (Caches
Therefore, lets consider the possible outcomes. What usually lush 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 diferent rows. Then it would not be unrea-
ean value change, it prints something and the program exits. sonable that they could be lushed in the opposite order from
53
ORACLE.COM/JAVAMAGAZINE /////////////////////////////////////////// JULY/AUGUST 2017
//ix 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
suicient 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.
Its probably fair to discuss briely how this code could
be made to behave in the expected way. I venture to suggest
that the expected behaviorthat is, the behavior implied by
Java Is Just
the source codeis that it should print value is 99 and then
stop. To achieve this, you must create a happens-before rela-
tionship between the write to hold[0] by the irst thread and
the Beginning
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
volatile variable happens before a subsequent read from that
services to build, test, deploy, and monitor.
same variable. Its probably tempting, then, to modify the
Oracle Cloud delivers.
hold variable to be volatile. But that would not work, because Start with Java in the cloudor choose whatever
the modiier 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
Its 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 efectively inal. You could, Oracle Cloud.
however, make hold into a simple static ield in the enclos- Built for modern app dev.
ing class and then label that static ield as volatile. Thats not
the only way, of course, but it would be suicient to solve this
Built for you.
particular problem. </article>

Simon Roberts joined Sun Microsystems in time to teach Suns Start here:
irst Java classes in the UK. He created the Sun Certiied Java developer.oracle.com
Programmer and Sun Certiied Java Developer exams. He wrote
several Java certiication 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 Oracles Java certiica-
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 weve 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 javamag_us@oracle.com.
tant to share with us or our readers. too. Please contact us with your ideas While it will have no inluence on our
Unless you speciically tell us that your at javamag_us@oracle.com and well 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 staf 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 youre 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 java@omeda.com, 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

Potrebbero piacerti anche