Professional Documents
Culture Documents
Java 9
and Beyond
eMag Issue 37 - January 2016
ARTICLE
ARTICLE
Programming with
modularity and
Project Jigsaw
ARTICLE
A Post-Apocalyptic
sun.misc.Unsafe
World
Java 9 and Beyond // eMag Issue 37 - Jan 2016
1
Programming with
modularity and
Project Jigsaw
A Tutorial Using the Latest Release Candidate
Project Jigsaw is the hallmark feature of Java
9, the next major version release of Java, and is
destined to bring modular programming into the
Java mainstream. After years of negotiating and
myriad JSRs and JEPs, Jigsaw is starting to take
its final form. This tutorial considers all aspects of
programming and migration to Project Jigsaw.
A Post-Apocalyptic sun.misc.
Unsafe World
The removal of sun.misc.Unsafe and other private APIs in
Java 9 has in recent weeks divided the Java community perhaps as never before in its 20 year history. Even though a
resolution has now been proposed and a migration path presented, the big question remains: What will a post sun.misc.
Unsafe world look like?
FOLLOW US
CONTACT US
GENERAL FEEDBACK feedback@infoq.com
ADVERTISING sales@infoq.com
EDITORIAL editors@infoq.com
facebook.com
/InfoQ
@InfoQ
google.com
/+InfoQ
linkedin.com
company/infoq
A LETTER FROM
THE EDITOR
If there were ever any question that Java was the
de facto standard for server side enterprise development, Java 8 has certainly quelled that one. The world
now anxiously awaits Java 9 and the innovations it
promises. Oracle has slated Java 9 for a March 2017
release.
In this eMag, we take a look at whats on the
scheduled horizon for Java 9 and beyond.
Project Jigsaw is the hallmark feature of Java 9
and is destined to bring modular programming into
the Java mainstream. After years of negotiating and
myriad JSRs and JEPs, Jigsaw is starting to take its final form. Nicolai Parlog gives us the definitive guide
to all aspects of programming and migration to Project Jigsaw.
Then Ben Evans takes a look at two long awaited
Java features, HTTP/2 and REPL. HTTP/2 addresses annoying problems coming from the rather rusty HTTP
support in Java. REPL is a shell scripted version of Java
that allows developers to quickly and interactively
Events
Health Rule Violations Started
IIS
Internet
Information
Services
Device
Java
Java
Transaction Scorecard
Java
Normal
Java
83.1%
963
Slow
0.3%
Very Slow
1.3%
15
Stall
Errors
0.2%
15.1%
175
Shipments DB
Java
When your business runs on Java, count on AppDynamics to give you the complete visibility you need to be
sure they are delivering the performance and business results you need no matter how complex,
distributed or asynchronous your environment, live in production or during development.
See every line of code. Get a complete view of your environment with deep code diagnostics and
auto-discovery. Understand performance trends with dynamic baselining. And drastically reduce time
to root cause and remediation.
See why the worlds largest Java deployments rely on the AppDynamics Application Intelligence
Platform. Sign up for a FREE trial today at www.appdynamics.com/java.
appdynamics.com
Advertising Feature
by Aakrit Prasad
Constant innovation in software is driving us toward a software revolution. That may be how the 21st century
will be best remembered. Among the popular software languages out there, however, Java continues to have
the largest industry footprint, running applications around the globe that produce a combined annual revenue
measuring trillions of dollars.
Thats why keeping up on the JDK is a high priority. Despite having a massive API to improve programming
productivity, Java has also grown due to its high-performance yet scalable JVM runtime, which ranks among
the fastest computing applications. As Javas footprint expands, JDK innovations continue to impact billions of
lines of code. As AppDynamics continues to grow, our focus towards supporting Java is only furthered by our
customer use and industry adoption of the JVM.
Discussion of Java 9 have been growing since the release of Java 8 in March 2014. The scope of various
JDK enhancements originally targeted for Java 9 has narrowed as the proposed release date of September 2016
has approached. Over 30 key enhancements, those with the potential for broadest impact, will be shared, and
discussion of some of these follows.
Project Jigsaw
HTTP/2 Client
Among the most popular Web protocols, HTTP has been getting its own
upgrade to HTTP/2 (with inspiration
from Googles SPDY/2), which boasts
significant network performance
gains. Java 9 will get its own HTTP
client API that implements HTTP/2
and WebSocket to replace the legacy
HttpURLConnection, which predates
HTTP/1.1 and has limitations such as
the one thread per request/response
behavior. Using HTTP/2 in Java 9, applications will perform and scale better with memory usage on par with
or lower than HttpURLConnection,
Apache HttpClient, and Netty.
jShell
Summary
Reference: http://openjdk.java.net/projects/jdk9/
Nicolai Parlog is a software developer and Java enthusiast. He constantly reads, thinks and
writes about Java, and codes for a living as well as for fun. Hes a long tail contributor to several
open source projects and blogs about software development on CodeFX. You can follow Nicolai
on Twitter.
Introducing Modules
Quoting from the highly recommended design overview State of the Module System by Oracle chief architect Mark Reinhold:
A module is a named, self-describing collection of
code and data. Its code is organized as a set of packages containing types, i.e., Java classes and interfaces; its
data includes resources and other kinds of static information.
To control how its code refers to types in other
modules, a module declares which other modules it requires in order to be compiled and run. To control how
code in other modules refers to types in its packages, a
module declares which of those packages it exports.
So in contrast to a JAR, a module has a name
that is recognized by the JVM, declares which other
modules it depends on, and defines which packages
are part of its public API.
Name
Module names can be arbitrary but must not conflict.
To that end it is recommended to use the standard
inverse-domain-name pattern of packages. While
this is not obligatory it will often mean that the module name is a prefix of the packages it contains.
Dependencies & Readability
A module lists the other modules it depends on to
compile and run. Again from the State of the Module System:
When one module depends directly upon another
[...] then code in the first module will be able to refer to
types in the second module. We therefore say that the
first module reads the second or, equivalently, that the
second module is readable by the first.
[]
The module system ensures that every dependence is fulfilled by precisely one other module, that no
two modules read each other, that every module reads
at most one module defining a given package, and that
modules defining identically-named packages do not
interfere with each other.
This concept of readability is the basis of reliable configuration: When any condition is violated,
the module system refuses to compile or launch
the code; an immense improvement over the brittle
classpath model.
Exports & Accessibility
A module lists the packages it exports. A type in one
module is only accessible by code in another module
if:
the type is public
the containing package is exported by the first
module
the second module reads the first
This means that public is no longer really public. A public type in a non-exported package is as
hidden from the outside world as a non-public type
in an exported package. So public is the new private, being even more hidden than package-private
types are today, because the module system does
not even permit access via reflection. As Jigsaw is
currently implemented, command line flags are the
only way around this.
So accessibility builds on top of readability and
the export clauses, creating the basis for strong encapsulation, where a module author can clearly express which parts of the modules API are public and
supported.
javafx.base,
graphics.
javafx.controls,
javafx.
001 jar -c
002 --file=mods/com.infoq.monitor.jar \
003 --main-class=com.infoq.monitor.
Monitor \
004 ${compiled class files}
The new --main-class can be used to specify the class containing the applications entry point.
The result is a so-called modular JAR, which we will
discuss further below.
In stark contrast to the old model, there is a
whole new sequence to launch the application. We
use the new -mp switch to specify where to look for
modules, and -m to name the one we want to launch:
java -mp mods -m com.infoq.monitor
To understand this a little better, lets talk about
how the compiler and the virtual machine handle
modules.
Kinds Of Modules
The JDK itself was modularized and consists of about
80 platform modules (have a look at them with java
-listmods). The ones that will be standardized for
Java 9 SE are prefixed with java., the JDK-specific
ones with jdk..
Not all Java environments have to contain all
platform modules. On the contrary, one goal of Jigsaw is the scalable platform, which means that it is
8
Figure 1
Service Monitor
src
com.infoq.monitor
com ...
module-info.java
com.infoq.monitor.db
com ...
module-info.java
com.infoq.monitor.stats
com ...
module-info.java
com.infoq.monitor.ui
com ...
module-info.java
Figure 2
001
002
003
004
005
module com.infoq.monitor.db {
requires java.logging;
requires java.sql;
exports com.infoq.monitor.db.write;
}
The user interface obviously requires the platform modules that contain the employed JavaFX
features. Its API consists of the means to launch the
JavaFX UI. This will return a model that uses JavaFX
properties. The client can update the model, and the
UI will show the new state.
001
002
003
004
005
006
007
module com.infoq.monitor.ui {
requires javafx.base;
requires javafx.controls;
requires javafx.graphics;
exports com.infoq.monitor.ui.launch;
exports com.infoq.monitor.ui.show;
}
10
Its a little unwieldy that we have to explicitly require javafx.base, but if we dont, we couldnt call
any code from javafx.beans.property, which we
must do to work with the model. So in a way com.
infoq.monitor.ui is broken without javafx.
beans.property. For this case the Jigsaw prototype
provides the concept of implied readability, which we
will cover shortly.
Our modularization creates a very different
module graph: (Figure 3)
Now lets take a look at some of the commands
used to compile, package, and launch our freshly
modularized application. This is how we can compile
and package modules that have no dependencies
outside of the JDK itself:
001 javac -d classes/com.infoq.monitor.
stats ${source files}
002 jar -c
003 --file=mods/com.infoq.monitor.stats.
jar \
004 ${compiled class files}
Like before and exactly as with Java 8, we compile the modules source, write the resulting files into
a subfolder of classes with the modules name, and
create a JAR in mods. Its a modular JAR because the
class files include the compiled module descriptor
module-info.class.
More interesting is how we process our only
module with dependencies on other application
modules:
001
002
003
004
005
006
007
008
javac \
-mp mods \
-d classes/com.infoq.monitor \
${list of source files}
jar -c
--file=mods/com.infoq.monitor.jar \
--main-class=com.infoq.monitor.
Monitor \
${compiled class files}
java -mp mods -m com.infoq.monitor
Implied Readability
A modules dependency on another module can take
two forms.
First, there are dependencies that are consumed internally without the outside world having
any knowledge of them. Take for example Guava,
where the code depending on a module does not
care at all whether it internally uses immutable lists
or not.
11
module com.infoq.monitor {
requires com.infoq.monitor.stats;
requires com.infoq.monitor.db;
requires com.infoq.monitor.ui;
// we dont need javafx.base anymore
to update the UI model
006 requires java.logging;
007 // no packages to export
008 }
12
module com.infoq.monitor.db {
requires java.logging;
requires java.sql;
exports com.infoq.monitor.db.write;
}
Aggregator Modules
Implied readability opens up the path to so-called
aggregator modules, which contain no code on their
own but aggregate a number of other APIs for easier
consumption. This is already being employed by the
Jigsaw JDK, which models compact profiles as modules that simply expose the very modules whose
packages are part of the profile.
In case of our microservice monitor we could
envision a single API module aggregating the modules for statistics, user interface and data, so that the
main module only has a single dependency:
001 module com.infoq.monitor.api {
002 requires public com.infoq.monitor.
stats;
003 requires public com.infoq.monitor.
db;
004 requires public com.infoq.monitor.ui;
005 // implied readability is not
transitive
006 // so we have to explicitly list
`javafx.base`
007 requires public javafx.base
008 }
009 module com.infoq.monitor {
010 requires com.infoq.monitor.api;
011 requires java.logging;
012 // no packages to export
013 }
This is useful in principal, but offers no particular advantage in this simple example.
Services
So far we have covered dependencies that are determined and declared at compile time. A looser
coupling can be achieved if a dependency takes
the form of a service, where one or more modules
provide a functionality, abstracted behind a single
type, and others consume instances of that type. The
module system can be used by the consumer to discover providers. This implements the service locator
pattern, where the module system itself acts as the
locator.
A service is a set of interfaces and (usually abstract) classes that provide a cohesive feature. All involved types must be accessible from a single type
(likely an interface) so that one can be used to load
the service.
A service provider module contains one or more
implementations of a service. For each it includes a
provides X with Y; clause in its module descriptor, where X is the fully qualified name of the service
interface and Y the fully qualified name of the implementing class. Y needs to have a public, parameterless constructor so that the module system can
instantiate it.
13
Figure 4
have to make sure that it still has access to that functionality. Its new module-info.java:
001
002
003
004
module com.infoq.monitor.stats {
requires java.logging;
requires com.infoq.monitor.watch;
// we have to declare which service
we are depending on
005 uses com.infoq.monitor.watch.Watcher;
006 exports com.infoq.monitor.stats.get;
007 }
14
Migration
So far we have discussed the scenario where a complete application including all its dependencies was
turned into modules. But when Jigsaw is first removed from its shiny new package, that will not be
very common; most projects will have dependencies
on libraries that were not yet adapted to work with
the module system, and over which they will have no
control.
As has been stated above, the whole application, including all of its dependencies, can simply be
put on the classpath. This is a crucial escape hatch in
case some problem prevents a migration.
We can now see why that approach works: All
artifacts on the classpath get rolled into the unnamed
module, where all types can freely access each other.
To use Javas public API they have to access the platform modules, which they can do since the unnamed
module reads all other observable modules.
A bottom-up migration starts with dependency-free artifacts, which can immediately be modularized. Building on that, other projects can move to
Jigsaw.
Clients can put modular JARs on the module
path and reference them by name if their projects
were migrated. Even if not and their code still comes
from the classpath, it can access the migrated artifacts because the unnamed module can read all
other modules. Or clients can decide to put modular
JARs on the classpath.
This approach works best for library projects
with few, well-maintained dependencies. But as the
number of dependencies grows, projects might not
be willing to wait for all of them to be modularized.
This is especially true of large Java applications,
which might prefer to opt for another approach.
A top-down migration starts with creating module descriptors for all artifacts of a project. They need
names and must specify which other internal artifacts they depend on and which packages they want
to export.
This process will naturally be confronted with
external dependencies. If Jigsaw-aware versions
exist for them and can be used, thats great. If not,
automatic modules are the way to go: The projects
artifacts require modules with the name that Jigsaw
derives from the artifact file names, and the artifacts
are placed on the module path.
It is sufficient to do this for direct dependencies
so that the new application modules can access them.
The dependencies likely bring transitive dependencies with them. But because the direct dependencies
were turned into automatic modules, which read all
other modules including the unnamed one, their dependencies can be put on the classpath.
For large projects this manual approach becomes unusable and build tools must help. Gradle
and Maven have already started to work on Jigsaw-related features.
More details about migration can be found in
the JavaOne talk Advanced Modular Development by
Alex Buckley and Alan Bateman, both members of
the Jigsaw team at Oracle.
15
module com.infoq.monitor.db {
requires java.logging;
requires java.sql;
requires guava;
exports com.infoq.monitor.db.write;
}
To compile it, we need to add libs to
the compilers module path:
javac \
-mp libs \
-d classes/com.infoq.monitor.db \
${list of source files}
Next Steps
We have explored the Jigsaw prototype and seen the
core features it has to offer. What else can we do besides waiting for Java 9?
Go deeper
It is always possible to learn more and there are a
couple of advanced topics we did not discuss:
The excellent State of the Module System
shows how modules can be used with reflection,
which includes adding read edges at run time and
the new concept of layers, as well as the interaction
with class loaders.
The new tool jlink can be used to create run
time images that only contain a specific set of platform modules; it is introduced in the Jigsaw QuickStart Guide, which is highly recommended.
These topics are also covered by talks the Jigsaw team gave at JavaOne 2015 and Devoxx BE 2015.
I summarized the former here.
16
Observe
All things Jigsaw should be discoverable from the
projects OpenJDK site. The main source for up-todate information on Project Jigsaw is the Jigsaw-Dev
mailing list. I will also continue to discuss this topic
on my blog.
Prepare
As has been hinted at, a migration to Jigsaw can be
a little rough. To prepare our projects we should examine whether they rely on anything that will be unavailable or removed in Java 9.
Dependencies on internal APIs, a crucial obstacle, can be analyzed with jdeps, the Java Dependency
Analysis Tool (introduction with some internal packages, official documentation for Windows and Unix),
which is already available in JDK 8. There are also
at least three jdeps-plugins for Maven: by Apache,
Philippe Marschall and myself. The latter enables a
project to gradually remove its dependencies on internal APIs while breaking the build on relapses.
If you are concerned about some specific API
that will be unavailable in Java 9, you could check
the mailing list of the corresponding OpenJDK project as these will be responsible for developing public
versions of them.
We should also identify the critical dependencies our projects rely on and check with those teams
how they are preparing for Java 9.
Adopt
Jigsaw early access builds are available and can be
used to tentatively compile and run existing projects. Unfortunately build system support is still incomplete, but its being worked on.
Information and problems gathered this way
can be returned to the project by posting on the
Jigsaw-Dev mailing list. To quote the (almost) final
words from one of the many involved JEPs:
It is impossible to determine the full impact of
these changes in the abstract. We must therefore rely
upon extensive internal andespeciallyexternal
testing. [] If some of these changes prove to be insurmountable hurdles for developers, deployers, or
end users then we will investigate ways to mitigate
their impact.
There is also the global Java User Group AdoptOpenJDK, which is a great contact for early adopters.
Ben Evansis the CEO of jClarity, a Java/JVM performance-analysis startup. In his spare time, he
is one of the leaders of the London Java Community and holds a seat on the Java Community
Process Executive Committee. His previous projects include performance testing the Google IPO,
financial trading systems, writing award-winning websites for some of the biggest films of the
1990s, and others.
Despite all the hype, Java9 will not just be about modularity. It is
targeting many additional pieces of functionality that are being
delivered as Java Enhancement Proposals (JEPs) implemented in
OpenJDK (the reference implementation for Java SE).
Some of the new JEPs may well
have a great impact on developers working lives during the
lifetime of Java 9. These include
HTTP/2 support and the JShell
REPL (read-eval-print loop) that
brings shell-based interactive
Java development and exploration of APIs.
HTTP/2
The HTTP/2 standard is a new
version of the HTTP protocol. The
existing version, HTTP/1.1, dates
17
001
002
003
004
005
006
007
008
Code 1
Akamai. HTTP/2 is therefore a
version optimized for the needs
of large, high-volume websites
and that places performance and
bandwidth consumption above
simplicity of implementation
and easy debugging.
The group chair summarizes some of thekey properties of
HTTP/2as follows:
the same HTTP APIs,
cheaper requests,
network friendly and server
friendly,
cache pushing,
being able to change your
mind, and
more encryption.
What does this mean for Java?
Java has supported HTTP since
version 1.0, but much of the code
comes from a very different era.
For example, Javas support is designed around a relatively protocol-agnostic framework (the URL
class) as it was not clear in the
late 1990s that the Web would
be the dominant force that it has
become.
The support was based on
best ideas at the time but the
world has experienced many
changes, not the least of which is
the fact that when Javas original
HTTP support shipped, HTTPS
didnt exist. So Javas APIs treat
HTTPS as an afterthought with
some irreducible complexity as
a result.
In the modern world, HTTPS
is becoming ubiquitous, with
HTTP moving towards becoming
a legacy technology. Even theUS
government has now adopted
JShell
Many languages feature interactive environments for exploratory development. In some cases
(notably Clojure and other Lisps),
the interactive environment is
where developers spend a large
amount or even the majority
of their coding time. Other languages, such as Scala or JRuby,
also make extensive use of REPLs.
Of course, Java has previously had the BeanShell scripting language, but this never
achieved full standardisation
and the project has become dormant in recent years. The inclusion of the Nashorn JavaScript
001
002
003
004
005
006
007
008
009
010
011
012
Code 2
implementation in Java 8 (and
the jjs REPL) opened the door to
broader consideration of REPLs
and the possibility of interactive
development in Java.
An effort to bring a modern
REPL to Java 9 has commenced
as JEP 222 under Project Kulla,
also known as JShell, in OpenJDK. The name Kulla refers to the
ancient Babylonian god of bricks
and foundations. The project
aims to provide an experience
as close to full Java as possible.
The project does not introduce
new non-Java syntax but instead
disables some features of the
language that are not useful for
interactive development (such as
top-level access-control modifiers or synchronized).
Like all REPLs, JShell provides a command line rather than
an IDE-like experience. Statements and expressions are evaluated immediately in the context
of an execution state, rather than
having to be packaged into classes. Methods are also free floating,
and do not have to belong to a
particular class. Instead, JShell
uses snippets of code to provide
a top-level execution environment.
JShell has been developed
in a separate project, like the
HTTP/2 API, in order to avoid impacting the stability of mainline
builds during a period of rapid
development. JShell is expect-
19
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
-> /help
Type a Java language expression, statement, or declaration.
Or type one of the following commands:
/l
or /list [all]
/seteditor <executable>
/e or /edit <name or id>
/d or /drop <name or id>
/s or /save [all|history] <file>
/o or /open <file>
/v or /vars
/m or /methods
/c or /classes
/x or /exit
/r or /reset
/f or /feedback <level>
verbose, default, or ?
/p or /prompt
/cp or /classpath <path>
/h or /history
/setstart <file>
/savestart <file>
/? or /help
/!
/<n>
/-<n>
017
-- toggle display of a prompt
018
-- add a path to the classpath
019
-- history of what you have typed
020
-- read file and set as the new start-up definitions
021
-- save the default start-up definitions to the file
022
-- this help message
023
-- re-run last snippet
024
-- re-run n-th snippet
025
-- re-run n-th previous snippet
026
027 Supported shortcuts include:
028
-- show possible completions for the current text
029 Shift- -- for current method or constructor invocation, show a synopsis of the
method/constructor
Code 3
001 -> System.out.print
002 print(
printf(
println(
Traditional expression evaluation is also easy, although Javas statically typed nature makes
this a little more exacting than
in dynamically typed languages. JShell automatically creates
temporary variables to hold the
values of expressions and ensure
that they remain in scope for later use (Code 4).
We can also view the source
code of everything entered in
the session so far, with the /list
command:
001 -> /list
002
9 : 3 * (4 + 5)
003
004
10 : System.out.
println($1);
The
command
/vars
shows all of the variables (both
20
001
002
003
004
005
006
-> 3 * (4 + 5)
| Expression value is: 27
|
assigned to temporary variable $1 of type int
-> System.out.println($1);
27
Code 4
001
002
003
004
005
006
007
008
009
010
011
012
Code 6
explicitly defined and temporaries) and the values they currently
hold (Code 5).
The REPL allows the simple
creation of classes and other user-defined types as well as small
bits of code. For example, classes
can be created in just one line,
like this (note that the starting
and closing braces are required):
001 -> class Pet {}
002 | Added class Pet
003
004 -> class Cat extends
Pet {}
005 | Added class Cat
The concise, free-flowing
nature of code in JShell means
that we can use the REPL to
demonstrate Java language features very simply. For example,
lets look at the well-known type
problem that Java arrays have
due to array covariance (Code 6).
This makes JShell a great
teaching or exploration tool, and
is closest in experience to the
Scala REPL. With the /classpath switch, additional jars can
be loaded to allow interactive
exploration of APIs directly from
the REPL.
Getting involved
Major IDEs are beginning to provide builds that support early
JDK9 includingNetBeansand
Eclipse. IntelliJ 14.1 reportedly
supports JDK 9, but it is unclear
how far the support for the new
modular JDK extends.
21
Monica Beckwithis a Java-performance consultant. Her past experiences include working with
Oracle/Sun and AMD to optimize the JVM for server-class systems. Monica was voted a Rock Star
speaker @JavaOne 2013 and was the performance lead for Garbage-First Garbage Collector (G1
GC). You can follow Monica on Twitter: @mon_beck
Why now?
Oracle is targeting OpenJDK 9 general availability
for September 2016. The hope is that the OpenJDK
community members that choose to work with early-access builds and release candidates will test the
feasibility of G1 GC as the default GC and provide
timely feedback and even code changes.
The only end users that will be impacted are
those who do not set an explicit GC today. These users will use G1 GC instead of the parallel GC they use
23
24
Summary
After much back and forth, Charlie Hunt, performance architect at Oracle, finally proposed the following steps in June 2015 (see this link):
Make G1 the default collector in JDK 9, continue
to evaluate G1, and enhance G1 in JDK 9.
Mitigate risk by reverting back to parallel GC before JDK 9 goes becomes generally available in
September 2016 if warranted by continuing to
monitor observations and experiences with G1 in
both JDK 9 pre-releases and the latest JDK 8 update releases.
Address enhancing ergonomics for selecting a
default GC as a separate JEP if future observations
suggest its needed.
Staffan Friberg of the Java SE Performance team
at Oracle urged the community to help gather data
points for the following key metrics (see this link):
Ensure that the G1 infrastructural complexity
doesnt introduce much delay at the JVM initialization.
G1 is going head to head with the throughput
GC. G1 also has pre and post write barriers. The
throughput metric is the key to understanding
how much of an overload the barriers impose on
the application.
G1 has remembered sets and collection sets that
increase the footprint. Data gathered from the
field should provide enough information to understand the impact of this increased footprint.
Acknowledgement
I would like to extend my gratitude to Charlie
Hunt for his review of this article.
Java Application
Performance
Monitoring
End-to-end transaction tracing
Code level visiblity
Dynamic baselining and alerting
Data rentention
Scalability
Supports all common
Java frameworks including:
Spring
Play
Grails
Resin
Apache CXF
Jetty
Tomcat
Glassfish
JBoss
WebLogic
WebSphere
Struts
Apache TomEE
Akka
For full list, go to:
AppDynamics.com/Java
Organization
A glance at the sun.misc.Unsafe feature set leads
to the unsettling realization that it was used as a
dumping ground for all kinds of features.
An attempt to categorize these features produces the followingfive sets of use cases:
atomic access to variables and array content, custom memory fences,
serialization support,
custom memory management and efficient
memory layout,
interoperability with native code or other JVMs,
and
advanced locking support.
In our quest for a replacement for all of this
functionality, wecan at least declare victory on the
last one; Java has had a powerful (and frankly very
nice) official API for this for quite some time, java.
util.concurrent.LockSupport.
Atomic access
Atomic access is one of the heavily used features
of sun.misc.Unsafe, featuring basic put and get
(with or without volatile semantics) as well as compare and swap (CAS) operations.
001 public long update() {
002 for(;;) {
003
long version = this.version;
004
long newVersion = version + 1;
005
if (UNSAFE.
compareAndSwapLong(this, VERSION_
OFFSET, version, newVersion)) {
006
return newVersion;
007
}
008
}
009 }
But doesnt Java support this through some official APIs? Absolutely, through the Atomic classes
and those are as ugly as the APIs based on sun.
misc.Unsafe and actually worse for other reasons.
AtomicX classes are real objects. Imagine that
we are maintaining a record inside a storage system
and we want to keep track of certain statistics or
metadata like version counters:
001 public class Record {
002 private final AtomicLong version =
new AtomicLong(0);
003
004 public long update() {
005
return version.incrementAndGet();
006 }
007 }
While the code is fairly readable, it is polluting our heap with two objects per data record instead of one, namely the Atomic instance as well as
the actual record itself. The problem is not only the
extraneous garbage generation, but also the larger
memory footprint and additional dereferences of the
Atomic instances.
We can do better with another API, the java.
util.concurrent.atomic.AtomicXFieldUpdater classes.
AtomicXFieldUpdaters are memory-optimized versions of the normal Atomic classes that
trade memory footprint for API simplicity. Using this
component, a single instance can support multiple
instances of a class, in our case Records, and can update volatile fields.
001 public class Record {
002 private static final
AtomicLongFieldUpdater<Record>
VERSION =
003
AtomicLongFieldUpdater.
newUpdater(Record.class,
version);
004
005 private volatile long version = 0;
006
007 public long update() {
008
return VERSION.
incrementAndGet(this);
009 }
010 }
This approach produces more efficient code for
object creation. Also, the updater is a static final field,
only a single updater is necessary for any number
of records, and most importantly it is available today. Additionally, it is a supported public API, which
should almost always be your preferred strategy. On
the other hand, looking at the creation and usage of
the updater, it is still rather ugly, not very readable,
and, frankly, counterintuitive.
But can we do even better? Yes, variable handles (affectionately called VarHandle) are on the
drawing board and offer a more attractiveAPI.
Variable handles are an abstraction over data
behavior. They provide volatile-like access, not only
over fields but also on elements inside arrays or buffers.
It might seem odd at first glance, so lets see
what is going on.
001 public class Record {
002 private static final VarHandle
VERSION;
003
004 static {
005
try {
006
VERSION = MethodHandles.
lookup().findFieldVarHandle
007
(Record.class, version,
long.class);
008
} catch (Exception e) {
009
throw new Error(e);
010
}
011 }
012
013 private volatile long version = 0;
014
015 public long update() {
016
return (long) VERSION.
addAndGet(this, 1);
017 }
018 }
27
being instantiated in an unsafe manner. Another interesting proposal isfrozen arrays, which might also
help serialization frameworks in the future.
It might look like the following snippet, whichis
totally my concoctionas there is no proposal yetbut
is based on the currently availablesun.reflect.ReflectionFactory API.
Serialization
This would call a special deserialization constructor that accepts a frozen char[]. The default
constructor of String creates a duplicate of the
passed char[] to prohibit external mutation. This
special deserialization constructor could prevent
copying the given char[] since it is a frozen array
(more on frozen arrays later). Again, remember this is
just my artificial rendition and will probably be different in the real draft.
Another important use case nowadays is serialization. Whether you are designing a distributed system,
you want to store serialized elements into a database, or you want to go off-heap, Java objects somehow need to be serialized and deserialized quickly.
The faster the better is the motto and to get there,
a lot of serialization frameworks use Unsafe::allocateInstance, which instantiates objects while
preventing constructors from being called, which is
useful in deserialization. This saves a lot of time and is
still safe since the previous object-state is recreated
through the deserialization process.
001 public String deserializeString()
throws Exception {
002 char[] chars =
readCharsFromStream();
003 String allocated = (String) UNSAFE.
allocateInstance(String.class);
004 UNSAFE.putObjectVolatile(allocated,
VALUE_OFFSET, chars);
005 return allocated;
006 }
(Please note that this code fragment might still
break in Java 9, even thoughsun.misc.Unsafewill
remain available, because theres an effort to optimize the memory footprint of a String. This will remove the char[] value in Java 9 and replace it with
a byte[]. Please refer to thedraft JEPon improving
memory efficiency in String for more details.)
There is not yet a replacement proposal forUnsafe::allocateInstance but the jdk9-dev mailing listis discussing certain solutions. One idea is to
move the private class sun.reflect.ReflectionFactory::newConstructorForSerialization into a
supported place that will prevent core classes from
28
Memory management
Possibly the most important usages for sun.misc.
Unsafe are reading and writing, not only to the heap,
as seen in the first section, but especially writing to
regions outside the normal Java heap. In this idiom,
native memory is acquired (represented through an
address/pointer) and offsets are calculated manually.
For example:
001 public long memory() {
002 long address = UNSAFE.
allocateMemory(8);
003 UNSAFE.putLong(address, Long.MAX_
VALUE);
004 return UNSAFE.getLong(address);
005 }
006 Some might jump in and say that the
same is possible using direct byte
buffers:
007 public long memory() {
008 ByteBuffer byteBuffer = ByteBuffer.
allocateDirect(8);
009 byteBuffer.putLong(0, Long.MAX_
VALUE);
010 return byteBuffer.getLong(0);
011 }
Interoperability
29
What else?
A few more things are floating around Project Valhalla and Project Panama. Some of those are not directly
related to sun.misc.Unsafe but are still worth mentioning.
Value types
Probably the hottest topic in these discussions isvalue types. These are lightweight wrappers that behave like Java primitives. As the name suggests, the
JVM is able to treat them like simple values, and can
do special optimizations that are not possible on
normal objects. You can think of those as user-definable primitive types.
001
002
003
004
005
006
007
30
Conclusion
Overall Im happy with the direction and accelerated
development of the JVM and Java as a language. A
lot of interesting and necessary solutions are underway and Java is converging on a modern state while
the JVM is providing new efficiencies and improvements.
From my perspective, people are definitely advised to invest in the genius piece of technology that
we call the JVM, and I expect that all JVM languages
will benefit from the newly integrated features.
In general, I highly recommend theJVMLS talks
from 2015 for more information on most of these
topics, and I suggest you read a summary of Brian
Goetzs talk aboutProject Valhalla.
ClassDynamic
One more interesting proposal floating around is
the so-calledClassDynamic. This proposal is probably in an earlier state than any Ive mentioned so far,
solittle information is currently available. But lets try
to anticipate whatit will look like.
A dynamic class brings the same generalization
concept as specialized generics but on a broader
scope. It provides some kind of template mechanism
to typical coding patterns. Imagine the returned collection fromCollections::synchronizedMapas a
pattern in which every method call is simply a synchronized version of the original
call:
001 R methodName(ARGS) {
002
synchronized (this)
{
003
underlying.
methodName(ARGS);
004
}
005 }
Using dynamic classes and
pattern templates supplied to
the specializer will dramatically
simplify the implementation of
recurring patterns. There is not
much available as I write thisbut
I hope to see more in the near
future, most probably as part of
Project Valhalla.
31
by Monica Beckwith
Sequential consistency
and data races
JMM-JSR133 talked about the
execution of a program with
respect to actions. Such an execution combines actions with
orders to describe the relationship of those actions. I would like
to expand on a few of the orders
and relationships and discuss
what constitutes a sequentially
consistent execution.
Lets start with program
order. A program order for each
thread is a total order that specifies the order in which the
thread would perform all actions. Sometimes, not all actions
need to be ordered, so we have
Thread b
r1 = x;
r2 = y;
if (r1 != 0)
if (r2 != 0)
y = 42;
x = 42;
This code is happens-before consistent but not really sequentially
consistent. For example, if r1 sees
the write of x = 42 and r2 sees the
write of y = 42, both x and y can
have a value of 42, which is the result of a data-race condition.
r1 = x;
y = 42;
r2 = y;
x = 42;
Here, both writes were committed before the read of their variables and the reads would see
the respective writes, and that
would lead to OoTA result.
In order to prohibit OoTA
values, some writes need to wait
for their reads to avoid data races.
The JMM-JSR133 OoTA prohibition formalized the disallowance
of OoTA reads. This formal definition consisted of executions and
causality requirements of the
memory model. Basically, a wellformed execution satisfies the
causality requirements if all of the
program actions could be committed. (A well-formed execution
happens in an intra-thread that
consistently obeys happens-before and synchronization-order
33
Bibliography
I have learned a lot from these
websites, which provide great
sample code sequences. My article should be considered an introductory article look at the
following for a deeper grasp of
the Java memory model.
JSR 133: JavaTM Memory
Model and Thread Specification Revision
The Java Memory Model
Java Concurrency (&C) blog
The jmm-dev Archives
The Java Language Specification, Ch. 17: Threads and Locks
Synchronization and the Java
Memory Model
All Accesses Are Atomic
Java Memory Model Pragmatics (transcript)
Memory Barriers: A Hardware
View for Software Hackers
Special thanks
I would like to thank Jeremy Manson for helping me correct my
various misunderstandings and
providing cleaner definitions
for terms that were new to me. I
would also like to thank Aleksey
Shipilev for helping with reducing the conceptual complexities
that were present in the draft version of this article. Aleksey also
guided me to his JMM pragmatics
transcript for deeper understanding, clarifications, and examples.
PREVIOUS ISSUES
35
This eMag provides a concise review of all that is essential for developers to know for building apps for the latest release of Apples mobile OS. This eMag is essentially
based on the video sessions from WWDC that Apple
made available to developers and tries to enrich them
with links to reference material that has become meanwhile available online.
34
Graph Databases
36
Patterns of DevOps
Culture
33
Cloud Migration