JDK 18 proposals: Java 18
Java 18 release is planned for 2021-03-22. Let’s have a look at what to expect in this release. I invite you for a quick overview of the features. Prepare yourself a cup of good coffee ☕!
The best place to track what JEPS are included for implementation on specific Java releases is openjdk release summary.
For Java 18 you should keep an eye on https://openjdk.java.net/projects/jdk/18/
This blog post is about some JEPs that are planned in release 18 of openjdk.
The GA (general availability) date of JDK 18 is 2022-03-22, so it is quite possible that the list of JEPS would actually lengthen with new additions.
As for today, there are eight JEPs targeted at Java 18:
- 400: utf-8 by default
- 408: simple web server
- 413: code snippets in java api documentation
- 416: reimplement core reflection with method handles
- 417: vector api (third incubator)
- 418: internet-address resolution spi
- 419: foreign function & memory api (second incubator)
- 420: pattern matching for switch (second preview)
Let’s have a closer look to some of them.
JEP descriptions below are just my notes made while I was reading the proposals. The proposals would probably evolve into new versions and the API proposed now may change as well.
My understanding of those JEPs is probably weak and leaky, so please don’t take anything you read for granted; rather use it as inspiration for your own (re)search.
UTF-8 by default
This JEP was created four years ago. It’s goal is to make Java programs more predicatable with regard to using charsets - in cases when there is no possibility to provide charset as API parameter it should be clear what charset is used.
For example, method and constructor references (::) in streams require single argument, so in such cases programmers cannot use additional “charset” parameter even if overloaded method/constructor version exists.
In such cases a platform-dependent charset is applied. In order to achieve predictable behavior and portable code on systems having different default charsets this JEP proposes that specific charset is used.
Default charset
The charset of choice is UTF-8. It is widely used on the web, in xml documents and on some great operating systems like Linux. It will by default be used throughout the standard API.
Default charset of current JDK can be checked using -XshowSettings:properties
parameter of java -version
:
|
|
Currently there are many APIs that use the default encoding:
- in
java.io
package, constructors of InputStreamReader, FileReader, OutputStreamWriter, FileWriter, and PrintStream - in
java.util
package, Formatter and Scanner - in
java.net
package, URLEncoder and URLDecoder (in deprecated methods)
The Change
The core change is this: the specification of Charset.defaultCharset() would now say that the default charset is UTF-8 unless configured otherwise by an implementation-specific means.
In order to use something different than UTF-8, users would be able to set file.encoding
to:
- COMPAT - which will enable pre-java 18 behavior
- UTF-8 - which will be a no-op
- something different - the behavior is not specified
The charset of System.out and System.err will be as specified by Console.charset().
Simple web server
The goal of JEP 408 is:
Provide a command-line tool to start a minimal web server that serves static files only. No CGI or servlet-like functionality is available. This tool will be useful for prototyping, ad-hoc coding, and testing purposes, particularly in educational contexts.
Commandline server
The second interesting JEP that landed in Java 18 is Java version of
|
|
The server would be started using a command very similar to python3 version:
|
|
which starts a server on default 8000 port.
However, you can specify other port:
|
|
or bind to all interfaces (note -b
- bind - option):
|
|
By default, the server serves files from the current working directory. You can override that using -p
option:
|
|
Commandline options
The -h
option displays a simple help message that lists all supported options:
|
|
Notes
- only HTTP is supported (no HTTPS support)
- mime tyeps are resolved automatically (.html files are served as text/html and .java files are served as text/plain) - this can be customized through
java.net.URLConnection::getFileNameMap
API - every request is logged to the console (by default the server behaves as if
-o info
was passed in commandline; you can use-o none
to disable logging or-o verbose
to have all you need) - server can be embedded in other applications using new API:
SimpleFileServer
,HttpHandler
, andRequest
(probably in com.sun.net.httpserver package)
SimpleHttpServer and API
New class SimpleHttpServer
allows to create a server, define a hander and create a Filter:
|
|
Create server programatically
This is how you can create simple server programatically.
|
|
This server:
- serves files from direcotory /my/data/dir
- logs with verbose level
- listens to connections on port 8080
Another option is to use create
method which was added to two existing classes: HttpServer
and HttpsServer
.
|
|
And now you can use it to create a customized server.
SimpleHttpServer customizations
What can be customized? For example, you can use different handlers for different contexts, one of them being created by new SimpleFileServer API.
How to use two handlers with two contetxts?
Have a look here:
- at context “/store/” there is a
SomePutHandler
registered which will handle the requests - context “/browse/” would be handled by a FileHandler created by using new API
SimpleFileServer.createFileHandler()
which would serve files from “/my/data/dir”
|
|
How to create an output filter?
Another example woud create a server that has an output filter defined; such filter would (probably) cause the SomePutHandler to have the output of the response redirected to standard output:
|
|
Request handling enhancements
New class HttpHandlers
has two static methods for handler creation.
|
|
Filter
abstract class allows the creation of a filter by changing (adapting) a request in some way:
|
|
They can be used in following way:
HttpHandlers.handleOrElse
to delegate processing to different handlers based on the state of the requestHttpHandlers.of
to create a handler that responds in the same wayRequest.with()
to modify/add a header to all incoming requests:
Request as immutable HttpExchange view
What’s interesting is that Filters use HttpExchange class which is a full, mutable state of the reqest whereas enhanced Filter’s adaptRequest
method uses limited view of the state represented by new interface request
:
|
|
Customization example
Here is the code that creates customized server. It has following capabilities:
- dispatches handling to different handlers:
SomePutHandler
orSomeHandler
based on the type of request method; if the method is PUT,SomePutHandler
is called - adds Foo header with value Bar
- listens on 8080 port
- will refuse new incomming connections if there are more that 10 already running
- will run on “/” context
|
|
Code Snippets
Writing solid, usable and informative code documentation requires both skills and tools. The standard tool is javadoc which by default uses Standard Doclet.
What is javadoc and doclet
Doclet is a program in Java that uses Javadoc API to render java language comments to a HTML format.
You can write your own doclets using Doclet API (also called javadoc API) and use it in javadoc
tool by giving -doclet
option, for example:
|
|
However, most programmers are not interested in writing doclets. They write code and want to document it and they just want the documentation to be automatically rendered to html. So they simply use javadoc with standard doclet and focus on writing doc comments using special tags (in a form @tag).
{@snippet …} tag
Java 18 will bring a new javadoc tag - @snippet - which will simplify adding example source code to API documentation.
Current approach is to include example code in <pre> {@code ….} </pre> blocks, however:
- tools cannot reliably apply syntax highlighting because there is no way to inform the tools about the kind of content
- comments /* … */ cannot be included in such blocks
- fragments cannot contain html markup
- fragments cannot use comment tags
New @snippet tag:
- may define inline snippet (included in code) or external snippet (read from external file)
- may define key-value pairs, so called attributes:
id
to define snippet’s identifier and create a link to it,lang
that defines programming language included in the snippet,file
defines location of external snippet,region
that declares the name of a region which will be defined using@start
and@end
tags within snippet’s inline comments
- may include java code, properties files content, source code in other languages or plain text
- inline tag may contain markup tags which indicate specific regions/lines and how to present them
Two restrictions of all tags apply also to @snippet tag:
- inline tag cannot use /* … */ comment because */ would terminate encosing documentation comment
- inline tag can only contain balanced pairs of curly braces so that the end of @snippet block can be identifed
Example of inline @snippet
|
|
Example of exernal snippet with a region
The external snippet uses:
file
attribute to point to the external file name andregion
attribute namedexample
that together with@start
and@end
tags marks the boundaries or the region of the code that will be included as the content of the snippet in javadoc :
|
|
where ShowOptional.java is a file containing:
|
|
Highlighting
For highlighting @highlight
can be used followed by arguments:
// @highlight substring="println"
- extracts substring and highlights it// @highlight region regex = "\barg\b"
followed by@end
- marks a region where highlighting is applied to all text matched by regex.type
parameter can be set tobold
,italic
orhighlighted
which will be converted to css classes of same names and which can be defined in system or user-defined stylesheet@replace regex='".*"' replacement="..."
- replaces all strings with ellipsis
Linking
The snippet can also contain links to external documentation, for example this code would generate a javadoc with a link to System.out
|
|
Using snippet with properties
An example of a property snippet:
|
|
Validation
The JEP proposal authors give a promise that Compiler Tree API will be extended to support @snippet tag. This will allow other tools to validate the content of the snippets:
- external snippets may be compiled in some contexts
- internal snippets can be wrapped so that they form a correct compilation unit, and also can be compiled or checked
Reimplement reflection with Method Handles
This is an implementation change in java.lang.reflect
but API remains the same.
This JEP aims at reducing maintanance cost of java.lang.reflect
and java.lang.invoke
APIs.
Its goal is to use method handles as the underlying mechanism of reflection, where currently also two other methods exist:
- calls to native code in HotSpot VM (only at the beginning of a program to enable fast startup): this type of reflection will still be there in early VM startup
- however, dynamic generation of bytecode stubs for Method::invoke, Constructor::newInstance, Field::get and Field::set - this will be replaced with java.lang.invoke API introduced in Java 7.
Compatibility
You can enable the old implementation using a flag:
-Djdk.reflect.useDirectMethodHandle=false
Vector API
This is third incubator phase and includes further fixes and enhancements as a result of received feedback.
The JEP focuses on providing new “vector API” that is platform independent. At runtime the code behind the API should reliaby compile to the optimal bytecode that uses vector instructions on supported CPUs.
Vector API has two implementations:
- pure java implementation (“funcitonal but not optimal”)
- vector operations for HotSpot C2 runtime compiler, where the computations are done om appropriate vector registers and using vector-related processor instructions.
A type that would be used o represent vector is Vector
The JEP mentions that currently only Linux and Windows will be supported, where MacOS support will come later.
Internet-Address Resolution SPI
The JEP prepares a service provider interface for host name and address resolution so that java.net.InetAdress can use other resolvers that the default (and too simple) platform resolver.
The default resolver uses hosts file and DNS. However:
- now address resolution is blocking a thread on system call; this is problematic for Project Loom which wants to use virtual threads and needs the address resolution operation to be non-blocking so that it serve other virtual threads while waiting for resolution operation to complete
- there are other protocols (like TLS or HTTPS) which could be used
- frameworks would have finer control over resolution
- it will simplify prototyping and testing, allowing fore example to writie a mock for network components that use InetAddress API
Foreign Function & Memory API
This is second incubator. The focus is to provide new API with which Java programs can use code and data outside of Java runtime:
- invoke foreign functions
- safely access memory not managed by JVM
- call native libraries
- process native data
The API allows client code in libraries and applications do the following (the new Java classes defining FFM API are given in braces):
- allocate foreign memory (MemorySegment, MemoryAddress, and SegmentAllocator)
- access and manipulate the memory (MemoryLayout, VarHandle)
- manage lifecycle of foreign resources (ResourceScope)
- call foreign functions (SymbolLookup, CLinker, and NativeSymbol)
Pattern matching for switch
This is second preview with some minor enhancements since the first preview in JEP 406:
- constant case label must appear before a guarded pattern of the same type example
- exhaustiveness checks with sealed hierarhies is more precise example
Summary
Majority of JEPS planned for Java 18 are enhancements to existing code. Top three JEPS actually introduce something new from the perspective of an average application developers:
- utf-8
- code snippets
- simple http server
These are the JEPS I focused the most, mainly because I think I understand them.
Others - like vector API or FFI - seem to me rather complex and I’m not an expert in those areas. In fact, I have rather basic understanding of what are the usecases for them.
For example, I have never written any JNI code so I won’t appreciate the abstraction and usefulness of FFI API. Likewise, I don’t create and process computer graphics pipelines nor implement neural networks where - I imagine - vector API would fit well. However, looking at the evolution of JEPs and seeing how Java platform expands to new areas gives me a very warm feeling that Java is not dead this is the platform where I want to stay and invest my time and energy.
Ten wpis jest częścią serii java.
- 2021-27-11 - JDK 18 proposals: Java 18