90 new features (and APIs) in JDK 11
- Transfer
Hi, Habr! I present to you the translation of the article " 90 New Features (and APIs) in JDK 11 " by Simon Ritter.
The new six-month JDK release cycle for many means that some have not even figured out what new features are in JDK 10, and on the verge of JDK 11. In one of the early blogs ( English ), all 109 new features and APIs were listed managed to be found in JDK 10. Therefore, for JDK 11, it was decided to do the same. However, a different format was chosen. This post will be divided into two sections: new features that are available to developers (public API) and everything else. Thus, if you are only interested in what directly affects your development, you can skip the second part.
The total number of changes that we managed to calculate turned out to be 90 (this is JEP plus new classes and methods, excluding separate methods for the HTTP client and Flight Recorder ) ( note of the translator: Java Flight Recorder (JFR) was one of the commercial additions from Oracle's built-in in the JDK, but since Java 11, thanks to JEP 328 , was transferred to open source) . Although JDK 11 was able to find eleven less changes than JDK 10, I think it is fair to say that more functionality was added to JDK 11, uniquely at the JVM level.
New visible to the developer features
There are quite a few changes in JDK 11 that could affect the style of development. There is a slight syntax change, a lot of new APIs and the ability to run applications in one file without using a compiler ( note the translator: the so-called shebang files ). In addition, a big (and breaking) change is the removal of the java.se.ee aggregation module , which may affect the transfer of an existing application to JDK 11.
JEP 323: Local-Variable Syntax for Lambda Parameters
JDK 10 introduced local variable output (or type inference) ( JEP 286 ). This simplifies the code, since you no longer need to explicitly specify the type of a local variable, you can use var instead . JEP 323 extends the use of this syntax, which is now also applicable to the parameters of lambda expressions. A simple example:
list.stream()
.map((var s) -> s.toLowerCase())
.collect(Collectors.toList());
An attentive Java programmer would point out that lambda expressions already have type inference, so using var would (in this case) be redundant. We could just as easily write the same code as:
list.stream()
.map(s -> s.toLowerCase())
.collect(Collectors.toList());
Why was it necessary to add var support? The answer is one special case - when you want to add annotation to the lambda parameter. It is impossible to do without the participation of any type. To avoid using an explicit type, we can use var to simplify things, thus:
list.stream()
.map((@Notnullvar s) -> s.toLowerCase())
.collect(Collectors.toList());
This change required changes to the Java Language Specification (JLS) , in particular:
Page 24: The description of the var special identifier.
Page 627-630: Lambda parameters
Page 636: Runtime evaluation of Lambda expressions
Page 746: Lambda syntax
JEP 330: Launch Single-File Source-Code Programs
One of the criticisms of Java is syntax redundancy, and the “ceremony” associated with the launch of even a trivial application can seriously raise the entry threshold for a beginner. To write an application that simply prints “Hello World!”, You need to write a class with a publicly available static void main method and use the System.out.println () method. Having done this, you must compile the code with javac. Finally, you can run an app that will greet the world. Running the same script in most modern languages is much easier and faster.
JEP 330 eliminates the need to compile a single-file application. Now just enter:
java HelloWorld.java
Java launcher identifies that the file contains Java source code and compiles the code into a * .class file before its execution.
Arguments placed after the source file name are passed as arguments when the application is started. Arguments placed before the source file name are passed as arguments to the java launcher after the code is compiled (this allows you to set things like the classpath on the command line). Arguments related to the compiler (for example, the path to the classes) will also be passed to javac for compilation.
Example:
java -classpath /home/foo/java Hello.java Bonjour
It will be equivalent to:
javac -classpath /home/foo/java Hello.java
java -classpath /home/foo/java Hello Bonjour
This JEP also provides support for shebang files. To reduce the need to even mention the java launcher on the command line, you can include it in the first line of the source file. For example:
#!/usr/bin/java --source 11publicclassHelloWorld{
...
The -source flag with the Java version used is mandatory.
JEP 321: HTTP Client (Standard)
JDK 9 has provided a new API to support the HTTP Client protocol ( JEP 110 ). Since JDK 9 provided the Java Platform Module System (JPMS) , this API was included as an incubator module . Incubator modules are designed to provide new APIs, but do not turn them into a Java SE standard. Developers can try the API by providing feedback. After making the necessary changes (this API has been updated in JDK 10), the API can be transferred to the main module to become part of the standard.
The HTTP Client API is now part of the Java SE 11 standard. This introduces a new module and package for the JDK, java.net.http . Main classes:
- Httpclient
- Httprequest
- HttpResponse
- Websocket
The API can be used synchronously or asynchronously. In asynchronous mode, CompletionFutures and CompletionStages are used.
JEP 320: Remove The Java EE and CORBA Modules
With the introduction of JPMS into JDK 9, it was possible to split the monolithic rt.jar file into several modules. An additional advantage of JPMS is that you can now create a Java runtime environment that includes only the modules necessary for your application, significantly reducing the overall size. Having explicitly defined boundaries, obsolete modules are now easier to remove from the Java API. This is what this JEP does; The java.se.ee meta module includes six modules that will no longer be part of the Java SE 11 standard and will not be included in the JDK.
Remote modules:
- corba ( approx. translator:
rest in peaceburn in hell ) - transaction
- activation
- xml.bind
- xml.ws
- xml.ws.annotation
These modules were marked obsolete (@Deprecated) since JDK 9 and were not included by default in the compilation or runtime. If you tried to compile or run an application that uses the API from these modules on JDK 9 or JDK 10, then you would fail. If you use API from these modules in your code, you will need to provide them as a separate module or library. Judging by the reviews, it seems that the java.xml modules that are part of the support for JAX-WS, SOAP web services are the ones that cause the most problems.
New public API
Many new APIs in JDK 11 are the result of the fact that the HTTP client module is now part of the standard, as well as the inclusion of Flight Recorder.
A complete sketchy list of API changes, including a comparison of different versions of the JDK, can be found here.
Here are all the new methods that are different from those contained in the modules java.net.http and jdk.jfr. Also, new methods and classes are not listed in the java.security modules, which are quite specific for JEP 324 and JEP 329 changes (there are six new classes and eight new methods).
java.io.ByteArrayOutputStream
- void writeBytes (byte []) : writes all the bytes from the argument to the OutputStream
java.io.FileReader
Two new constructors that allow you to specify Charset.
java.io.FileWriter
Four new constructors that allow you to specify Charset.
java.io.InputStream
- io.InputStream nullInputStream () : returns an InputStream that does not read bytes. Looking at this method (and the one in the OutputStream, Reader and Writer), the question arises as to why it can be useful. You can think of them as / dev / null — to throw out output that you don’t need, or to provide input that always returns zero bytes.
java.io.OutputStream
- io.OutputStream nullOutputStream ()
java.io.Reader
- io.Reader nullReader ()
java.io.Writer
- io.Writer nullWriter ()
java.lang.Character
- String toString (int) : This is the overloaded form of the existing method, but instead of char, an int is used. Int - Unicode code point.
java.lang.CharSequence
- int compare (CharSequence, CharSequence) : compares two instances of CharSequence lexicographically . Returns a negative value, zero or a positive value if the first sequence is lexicographically less, equal to or greater than the second, respectively.
java.lang.ref.Reference
- lang.Object clone () : I must admit, this change causes confusion. The Reference class does not implement the Cloneable interface, and this method throws a CloneNotSupportedException exception. There must be a reason for including it, perhaps for something in the future. ( comment of the translator: there is a discussion on StackOverflow , a ticket in OpenJDK )
java.lang.Runtime
java.lang.System
There are no new methods here, but it is worth mentioning that the runFinalizersOnExit () method has now been removed from both classes (there may be a problem when migrating to JDK 11).
java.lang.String
I think this is one of the highlights of the new APIs in JDK 11. There are some useful new methods here.
- boolean isBlank () : returns true if the string is empty or contains only spaces, false otherwise.
- Stream lines () : returns a Stream from a String extracted from this string, separated by a string delimiter.
- String repeat (int) : returns a string whose value is the concatenation of this string repeated a number of times.
- String strip () : Returns a string whose value is this string, this removes all spaces at the beginning and at the end of the string.
- String stripLeading () : returns a string whose value is this string, all spaces at the beginning of the string are removed.
- String stripTrailing () : returns a string whose value is this string, and all spaces at the end of the string are deleted.
Most likely, you look at strip () and ask: “How does this differ from the existing trim () method ?” The answer lies in the difference in the definition of spaces. ( comment of translator: in short, strip () understands Unicode better, detailed parsing on StackOverflow )
java.lang.StringBuffer
java.lang.StringBuilder
Both of these classes have a new compareTo () method that accepts a StringBuffer / StringBuilder and returns an int. The lexical comparison method is similar to the new compareTo () method in CharSequence.
java.lang.Thread
No new methods. The destroy () and stop (Throwable) methods have been removed. The stop () method , which takes no arguments, is still present. May lead to compatibility issue.
java.nio.ByteBuffer
java.nio.CharBuffer
java.nio.DoubleBuffer
java.nio.FloatBuffer
java.nio.LongBuffer
java.nio.ShortBuffer
All of these classes now have a mismatch () method , which finds and returns the relative index of the first mismatch between this buffer and the transferred buffer.
java.nio.channels.SelectionKey
- int interestOpsAnd (int) : Atomically sets the key's interest to the bitwise intersection (“and”) of the existing set of interests and the value passed.
- int interestOpsOr (int) : Atomically sets the key's interest to the bitwise union (“or”) of the existing set of interests and the value passed.
java.nio.channels.Selector
- int select (java.util.function.Consumer, long) : select and perform actions on the keys whose corresponding channels are ready for I / O operations. long argument is a timeout.
- int select (java.util.function.Consumer) : the same as above, but without a timeout.
- int selectNow (java.util.function.Consumer) : the same as above, only non-blocking.
java.nio.file.Files
- String readString (Path) : reads all content from file to string, decoding from bytes to characters using UTF-8 encoding.
- String readString (Path, Charset) : as stated above, with the difference that decoding from bytes to characters occurs using the specified Charset.
- Path writeString (Path, CharSequence, java.nio.file.OpenOption []) : Write CharSequence to a file. Characters are encoded in bytes using UTF-8 encoding.
- Path writeString (Path, CharSequence, java.nio.file.Charset, OpenOption []) : the same as above, characters are encoded in bytes using the charset specified in Charset.
java.nio.file.Path
- Path of (String, String []) : Returns a Path from a string argument to a path or a sequence of strings, which when combined form a string path.
- Path of (net.URI) : Returns a Path from a URI.
java.util.Collection
- Object [] toArray (java.util.function.IntFunction) : returns an array containing all the elements in this collection, using the provided generation function to allocate the returned array.
java.util.concurrent.PriorityBlockingQueue
java.util.PriorityQueue
- void forEach (java.util.function.Consumer) : Performs the passed action for each Iterable until all the elements have been processed, or the action throws an exception.
- boolean removeAll (java.util.Collection) : removes all the elements of this collection that are also contained in the specified collection (optional operation).
- boolean removeIf (java.util.function.Predicate) : Removes all elements from this collection that satisfy the given predicate.
- boolean retainAll (java.util.Collection) : Saves only those elements in this collection that are contained in the passed collection (optional operation).
java.util.concurrent.TimeUnit
- long convert (java.time.Duration) : converts the transmitted Duration to this type.
java.util.function.Predicate
- Predicate not (Predicate) : Returns a predicate that is the negation of the predicate passed.
This is one of my favorite new APIs in JDK 11. As an example, you can convert this code:
lines.stream()
.filter(s -> !s.isBlank())
at
lines.stream()
.filter(Predicate.not(String::isBlank))
or if we use static import:
lines.stream()
.filter(not(String::isBlank))
Personally, I think this version is more understandable and concise.
java.util.Optional
java.util.OptionalInt
java.util.OptionalDouble
java.util.OptionalLong
- boolean isEmpty () : Returns true if not present, otherwise false.
java.util.regex.Pattern
- Predicate asMatchPredicate () : I think it might be the pearl of the new JDK API 11. It creates a predicate that checks whether this pattern matches the given input string.
java.util.zip.Deflater
int deflate (ByteBuffer) : compresses the input and fills the specified buffer.
int deflate (ByteBuffer, int) : compresses the input and fills the specified buffer. Returns the actual amount of compressed data.
void setDictionary (ByteBuffer) : Sets the specified dictionary to be compressed into bytes in this buffer. This is an overloaded form of an existing method that can now accept a ByteBuffer, rather than a byte array.
void setInput (ByteBuffer) : Sets the input for compression. Also the overloaded form of the existing method.
java.util.zip.Inflater
- int inflate (ByteBuffer) : unpacks the bytes into the specified buffer. Returns the actual number of unzipped bytes.
- void setDictionary (ByteBuffer) : Sets the specified dictionary to bytes in this buffer. The overloaded form of the existing method.
- void setInput (ByteBuffer) : Sets the input for decompression. The overloaded form of the existing method.
javax.print.attribute.standard.DialogOwner
This is a new class in JDK 11. Used to support a print dialog request or page setup. Must be displayed on top of all windows or a specific window.
javax.swing.DefaultComboBoxModel
javax.swing.DefaultListModel
- void addAll (Collection) : adds all the elements present in the collection.
- void addAll (int, Collection) : adds all the elements present in the collection, starting at the specified index.
javax.swing.ListSelectionModel
- int [] getSelectedIndices () : Returns an array of all selected indexes in the selected model, in ascending order.
- int getSelectedItemsCount () : Returns the number of selected items.
jdk.jshell.EvalException
- jshell.JShellException getCause () : returns a throwable cause wrapper in the executing client represented by EvalException, or null if the cause does not exist or is unknown.
New features (non-public API)
JEP 181: Nest-Based Access Control
Java (and other languages) supports nested classes through inner classes. For proper operation, the compiler must perform some tricks. For example:
publicclassOuter{
privateint outerInt;
classInner{
publicvoidprintOuterInt(){
System.out.println("Outer int = " + outerInt);
}
}
}
The compiler modifies this to create something like this before compiling:
publicclassOuter{
privateint outerInt;
publicint access$000() {
return outerInt;
}
}
classInner$Outer{
Outer outer;
publicvoidprintOuterInt(){
System.out.println("Outer int = " + outer.access$000());
}
}
Although, logically, the inner class is part of the same code as the outer class, it is compiled as a separate class. Therefore, this requires a synthetic method ("bridge"), which must be created by the compiler to provide access to the private field of the outer class.
This JEP represents the concept of "nest", where two members of the same nest (Outer and Inner from our example) are neighbors. Two new attributes were added to the * .class file format: NestHost and NestMembers. These changes are also useful for other bytecode-compiled languages that support nested classes.
This feature provides three new methods for java.lang.Class:
- Class getNestHost ()
- Class [] getNestMembers ()
- boolean isNestmateOf (clazz)
This feature also required changes to the Java Virtual Machine Specification (JVMS) , particularly in section 5.4.4 “Access Control”.
JEP 309: Dynamic Class-File Constants
This JEP describes the extension of the * .class file format to support the new form with the constant pool CONSTANT_Dynamic (often referred to in presentations as condy). The idea of a dynamic constant seems like an oxymoron, but, in fact, you can think of it as a final meaning in Java. The value of the constant pool is not set at the compilation stage (unlike other constants), but is used the bootstrap method to determine the value at run time. Therefore, the value is dynamic, but since its value is specified only once, it is also constant.
This function will be primarily useful to those who develop new languages and compilers. Who will generate the bytecode and * .class files in to run on the JVM. This will simplify some tasks.
This feature provides a new java.lang.invoke.ConstantBootstraps class with nine new methods. I will not list them all here; these are methods for initial loading of dynamically calculated constants.
This feature required changes to the JVMS, in particular, the way the special invoke byte code and section 4.4 “The Constant Pool” are used.
JEP 315: Improve Aarch64 Intrinsics
It was a Red Hat JEP. The JVM can now use more specialized instructions available in the Arm 64 command set. In particular, this improves the sin (), cos () and log () methods of the java.lang.Math class.
JEP 318: The Epsilon Garbage Collector
Red Hat also contributed to this JEP. The Epsilon garbage collector is somewhat unusual, as it does not collect garbage! It will allocate new memory if it is required when creating new objects, but it does not free up the space occupied by objects without references.
It would seem, then what is the point? There are at least two uses:
- First of all, this collector is designed so that the new GC algorithms are evaluated in terms of their performance impact. The idea is to run a sample application with Epsilon GC and generate a metric. The new GC algorithm is turned on, the same tests are run and the results are compared.
- For very short or short-lived tasks (think about serverless functions in the cloud), where you can guarantee that you will not exceed the memory allocated to the heap space. This can improve performance due to the absence of overheads (including collecting the statistics necessary to make a decision about running the collector) in the application code.
If the heap space is exhausted, the subsequent work of the JVM can be configured in one of three ways:
- Called normal OutOfMemoryError.
- Perform heap reset
- Hard stop the JVM and possibly perform an external task (for example, starting a debugger).
JEP 324: Key Agreement with Curve25519 and Curve448
Cryptographic standards are constantly changing and improving. In this case, the existing Diffie-Hellman scheme with an elliptic curve is replaced by Curve25519 and Curve448. This is the key agreement scheme defined in RFC-7748.
The Java platform supports Unicode to ensure that all character sets are processed. Since Unicode has been upgraded to version 10 , the JDK has also been updated to support this version of the standard.
I am always intrigued to see what Unicode developers include in newer versions. Unicode 10 has 8,518 new characters. This includes the Bitcoi symbol, the Nüshu character set (used by Chinese women for writing poetry), and Soyombo and Zanabazar Square (are symbols used in historical Buddhist texts for writing Sanskrit, Tibetan and Mongolian languages). There are also many other Emoji, including the long-awaited (apparently) Colbert Emoji .
Remember that starting with JDK 9, you can use UTF-8 in properties files (.properties). This means that any Unicode character can be used in such files. Including emojis. Or Nüshu.
Flight Recorder is a low-level data collection structure for the JVM. Prior to JDK 11, this was a commercial function in a complete Oracle JDK suite. Now that Oracle has eliminated the functional differences between Oracle JDK and OpenJDK, this feature has been added to OpenJDK.
JEP identifies four basic properties:
- Providing API for writing and reading data as events
- Provide a buffer mechanism and binary data format
- Allow configuration and filtering of events
- Provide events for OS, JVM HotSpot and JDK libraries
There are two new modules for this: jdk.jfr and jdk.management.jfr.
JEP 329: ChaCha20 and Poly1305 Cryptographic Algorithms
Like JEP 324, this is an update of the ciphers used by the JDK. Implement the ChaCha20 and ChaCha20-Poly1305 ciphers, as specified in RFC 7539. ChaCha20 is a relatively new stream cipher that can replace the old, insecure RC4 stream cipher.
JEP 331: Low-overhead Heap Profiling
It is a little surprising that this is JEP, was introduced by Google. This makes it possible to obtain information about the distribution of heaps of Java objects in the JVM.
Basic properties:
- Low enough workload to be enabled by default continuously
- Available through a well-defined software interface.
- May display all distributions
- Can be defined in an implementation independent manner (i.e., not limited to a specific GC algorithm or VM implementation)
- Can provide information about Java live and dead objects.
JEP 332: Transport Layer Security (TLS) 1.3
TLS 1.3 (RFC 8446) is the "overhaul" of the TLS protocol and provides a significant increase in security and performance over previous versions. The JDK now supports this, although it does not apply to Datagram Transport Layer Security (DTLS).
JEP 333: ZGC A Scalable, Low Latency Garbage Collector
This is a new experimental garbage collector designed for use with applications that require a large (multi-gigabyte) heap and low latency. It uses a bunch of one generation (which is a bit unusual, given the generally accepted pattern of using Weak Generational Hypothesis ) and performs most (but not all) GC work simultaneously with the application. This is done using the "barrier" mechanism for reading, which intercepts every reading of an object from the application and ensures the return link is correct. This eliminates the problem of simultaneously moving objects while the application flows.
ZGC is a region-based (like G1), NUMA aware and compacting garbage collector. Not intended as a general purpose collector.
If you really want a low latency pauseless garbage collector, wholeheartedly I can recommend the C4 in our Zing JVM.
JEP 335: Deprecate the Nashorn Scripting Engine
Nashorn was introduced in JDK 8 as a more efficient replacement for Rhino Javascript engine. The goal is to remove Nashorn along with the API and jjs tool from a future version of Java. When this happens, is not yet decided. The possibility of using Graal VM as a replacement was suggested, but how it will work is still unclear.
JEP 336: Deprecate the Pack200 Tools and APIs
Pack200 is a compression scheme for JAR files, used since Java SE 5.0. With the introduction of JPMS into JDK 9, the Pack200 is no longer used to compress the JDK itself. The pack200 and unpack200 and API Pack200 tools in java.util.jar are now obsolete and may be removed in a future version of the JDK. When this happens, not specified.
findings
JDK 11 is the next version of the LTS JDK (this is Orakl followed by all others). Although there are not so many developer-oriented functions, much has changed in the JVM, it lays the foundation for future more important functions.
Zulu build JDK 11 can be found here and is absolutely free!
Is it time to start migrating your applications to JDK 11?
( note of translator: request, all translation errors and other inaccuracies sent to the LAN )