📜 ⬆️ ⬇️

39 new features that will be available in Java 12

From the wonderful interview on Habré: “Simon Ritter is the man who worked on Java from the very beginning and continues to do this as Deputy Technical Director of Azul, the company working on the Zing JVM virtual machine and one of the best garbage collectors, C4 (Continuously Concurrent Compacting Collector) »
Below is a translation of his article on new features for JDK 12 and some of the difficulties you may encounter when migrating to a new build.

I have written several blog posts listing all of the changes for each of the latest Java releases ( JDK 10 , JDK 11 ). Now I will look at the dark side of JDK 12, focusing on some of the pitfalls that can cause problems if you want to move the application to this version.



In JDK 12, the fewest new features in all of the Java releases to date (I counted 109 in JDK 10 and 90 in JDK 11). This is not bad - due to release cycles, some versions will contain more changes, and some less.


I will break new functions into obvious logical areas: Java language, libraries, JVM and other JDK functions.


Language changes


The function that I (and I assume that many other people) will consider most noticeable in JDK 12 is the new switch statement ( JEP 325 ). This is also the first language change that will be used as a “preview” function. The idea of ​​a “preview” was introduced in early 2018 as part of JEP 12 . In essence, this is a way to enable beta versions of new features using command line options. Using the preview it is still possible to make changes based on user feedback, and as a last resort, completely remove the function if it has not been accepted properly. The key point in the preview features is that they are not included in the Java SE specification. About the new switch there is a very good translation on Habré.
In JDK, 12 switch has become an expression that evaluates its "content" to produce a result. Immediately I will explain that this does not affect backward compatibility, so you do not need to change any code that uses switch as an operator.


I will use the example from JEP, since it is simple and straightforward:


Old switch
int numLetters; switch (day) { case MONDAY: case FRIDAY: case SUNDAY: numLetters = 6; break; case TUESDAY: numLetters = 7; break; case THURSDAY: case SATURDAY: numLetters = 8; break; case WEDNESDAY: numLetters = 9; break; default: throw new IllegalStateException("Huh? " + day); } 

As you can see, we associate the day of the week with the name of the variable day , then assign the value numLetters . Now that switch is an operator, we can do the assignment once (significantly reducing the likelihood of an error code) using the result of the switch statement:


 int numLetters = switch (day) { case MONDAY, FRIDAY, SUNDAY -> 6; case TUESDAY -> 7; case THURSDAY, SATURDAY -> 8; case WEDNESDAY -> 9; default -> throw new IllegalStateException("Huh? " + day); }; 

You will quickly notice two changes in the syntax. The developers of OpenJDK stumbled upon a little-known syntactic function called “comma-separated list”. Also, the lambda expression operator -> simplifies the return value. You can still use break with value if you really want it. There are several other details about this feature, but it is probably easier to read the JEP.


Libraries


There is one change that I find very useful. There are also a number of minor ones.


teeing collector


In the Streams API, as usual, a new Collector has appeared, provided by the service class Collectors. A new collector can be obtained using the teeing() method. The teeing collector takes three arguments: two collectors and a bifunction. To understand the work of this collector, I recommend this article on Habré .
To understand how he does this, I drew a diagram:


image

All values ​​from the input stream are transmitted to each collector. The result of each collector is passed as arguments to BiFunction for and generating the final result.


A simple example is the calculation of the average (yes, I know that there are already collectors for this, for example averagingInt() , but this is a simple example to help understand the concept).


 /* Assume Collectors is statically imported */ double average = Stream.of(1, 4, 2, 7, 4, 6, 5) .collect(teeing( summingDouble(i -> i), counting(), (sum, n) -> sum / n) ); 

The first collector calculates the sum of the input stream, and the second - the number of elements. BiFunction divides the sum by the number of elements to get the average value.


java.io


InputStream skipNBytes(long n) - skips and drops exactly n bytes from the InputStream input stream. If n is zero or less, bytes are not skipped.


java.lang


There is a new package, java.lang.constant, which is part of the API constant JVM, JEP 334 .


Each Java class file has a constant pool in which the operands for the bytecode instructions in the class are stored. Developers find it difficult to manipulate class files due to class loading problems. The constant JVM API provides symbolic reference types to describe each form of a constant (class, loadable constant, MethodHandle , MethodHandle constant, MethodType constant).


This also affected several other classes. All of the following classes now have a describeConstable() method:



As a Brit, I find it pretty funny. The term “Constable” (Constable, describeConstable ) has been used since the 11th century, and this is how we often refer to the police. It is also the name of a famous 18th century artist, John Constable. It makes me wonder if the future version will describeTurner() . Obviously, in this case, the abbreviation Constant Table , not related to the employee of the law or landscape painter.


The following classes now include the resolveConstantDesc() method:



java.lang.Character


Internal classes have been updated to include new Unicode blocks. I always like to see what people have found to add to Unicode, here are some examples:



java.lang.Class


arrayType() returns Class for an array type whose component type is described by this Class . This can be verified using jshell :


 jshell> (new String[2]).getClass().getName() $11 ==> "[Ljava.lang.String;" jshell> (new String[2]).getClass().arrayType() $12 ==> class [[Ljava.lang.String; jshell> "foo".getClass().arrayType() $15 ==> class [Ljava.lang.String; 

I'm not quite sure what the meaning of this method is, since all it does is add Class to the type that this class represents.


componentType() is the same as getComponentType() . This begs the question - why add a redundant method?


descriptorString() - again, returns the same result as getName() . However, it is required because Class now implements the TypeDescriptor interface associated with the new API constant JVM.


lava.lang.String


indent() - adds a number of leading spaces to the string. If the parameter is negative, then the number of leading spaces will be removed (if possible).


transform() - Applies the provided function to a string. The result may not be a string.


java.lang.invoke


VarHandle now has toString() to return a compact description.


java.net.SecureCacheResponse and java.net.ssl.HttpsConnection have a new method, getSSLSession() which returns an Optional containing the SSLSession used in the connection.


java.nio.files


The Files class has a new method, mismatch() , which finds and returns the position of the first non-matching byte in the contents of the two files, or -1L if there is no discrepancy.


java.text


There is a new class CompactNumberFormat . It is a subclass of NumberFormat that formats a decimal number in a compact form. An example of a compact form is 1M instead of 1000000 , thus it requires two instead of nine characters. NumberFormat and java.text.spi.NumberFormatProvider have been extended to include the new getCompactNumberInstance() method. There is also a new enum, NumberFormatStyle which has two values: LONG and SHORT.


java.util.concurrent


CompletionStage now includes several overloaded forms with three methods:



These methods extend the ability to create a new CompletionStage from the existing, CompletionStage if the current one ends with an exception. Check the API documentation for details.


javax.crypto


The Cipher class has a new toString() method that returns a string containing the transform, mode, and provider Cipher .


javax.naming.ldap.spi


This is a new package in JDK 12 and it contains two classes — LdapDnsProvider , which is the service provider class for DNS lookup for LDAP operations, and LdapDnsProviderResults which encapsulates the DNS search result for the LDAP URL.


Swing


Swing is still being updated! Yes, filechooser.FileSystemView now has a new getChooserShortcutPanelFiles() method. It returns an array of files representing the values ​​to display by default in the pane of file selection labels.


JVM Changes


JEP 189: Shenandoah : Low-Pause-Time Garbage Collector


Shenandoah is a research project announced by Red Hat in 2014 that focuses on low-latency application requirements for memory management in the JVM. Its goals are the maximum pause time of 1..10ms for a heap of more than 20 GB ( so it is not intended for small applications. - as one of the developers of Shenandoah responded , this is not the case and it does an excellent job with small applications). This collector is designed to work in parallel with the application flows, so avoid the problems that we see in most garbage collectors.


JEP 344: G1 Mixed Collections


This change is intended to improve the behavior of the G1 collector when it reaches the specified delay target. G1 divides the heap space (both old and old) into regions. The idea is that in the old generation there is no need to collect garbage in one operation. When G1 needs to collect garbage, it selects the regions it determines. This is called a collection set. Before JDK 12, when work began on a set, all work had to be completed, in fact, as an atomic operation. The problem was that sometimes due to changes in the use of the heap space by the application, the collection set was too large and took too long to collect, which caused the pause time not to be reached.


In JDK 12, if G1 identifies this situation, it will interrupt data collection halfway, if it does not affect the ability of the application to continue to allocate space for new objects. The net effect of G1 will be better when a short pause time is reached.


JEP 346: quickly return unused allocated memory from G1


This is another performance improvement for G1, but another is related to how the JVM interacts with the rest of the system. Obviously, the JVM heap requires memory, and on startup it requests memory from the operating system's virtual memory allocator. When an application is started, there may be cases where the amount of memory required for the heap drops and some of the allocated memory can be returned to the operating system for use by other applications.


G1 already does this, but can only do it in one of two places. Firstly, during the complete collection, and secondly, during one of the parallel cycles. G1 tries not to do a full charge, and with low memory usage there can be significant periods between acquisition cycles. This leads to the fact that G1 can retain a fixed memory for a long time.


In JDK 12 G1, the application will periodically attempt to continue or start a parallel loop to determine the general use of the Java heap during idle. Unused memory can be returned to the operating system in a more timely and predictable manner.


The new command line flag -XX:G1PeriodicGCInterval can be used to set the number of milliseconds between checks.


This feature will lead to more conservative use of JVM memory for applications that are idle for long periods of time.


Other new JDK features


JEP 230: Microbranking Kit


Java Microbenchmarking Harness (JMH) was developed by Alexey Shipilev when he worked at Oracle, and provides an extensive platform for developing performance tests for Java applications. Alexey did an outstanding job helping people to avoid the many simple mistakes that they make when trying to analyze application performance: warm up, avoid exceptions, etc.


JMH can now be included in OpenJDK. Anyone who is interested in working on the JDK itself and changing the code can use it to compare performance both before and after their changes, as well as to compare performance in different releases. A series of tests are included to enable testing; The design of JMH is such that it is easy to add new tests to where it is needed.


JEP 340: one Aarch64 port, not two


OpenJDK has two ports for the Arm64 architecture, one of which is provided by Oracle and the other by Red Hat. Since this was not necessary, and Oracle stopped supporting Arm for its binary JDK files, it was decided to use only the Red Hat port, which is still supported and developed.


JEP 341: Default CDS Archives


The Data Sharing (CDS) class used to be a commercial function in Oracle JDK. With a recent transition made in JDK 11, to eliminate all the functional differences between Oracle JDK and OpenJDK, it was included in OpenJDK.


CDS requires an archive created for classes that are loaded when the application starts. In JDK 12 for 64-bit platforms, there is now a classes.jsa file in the lib/server directory. This is the CDS archive for “default classes”. I assume that it means all open classes in JDK modules; I could not find a way to unpack it to check. Since CDS is enabled by default, which is equivalent to the -Xshare:auto options on the command line, users will benefit from improved application launch time from it.


findings


JDK 12 provides a small number of new features and APIs, with the switch expression being the most interesting for developers. G1 users will surely appreciate the performance improvements.


With the new version of the release, I would advise all users to test their applications in this release. Tracking incremental changes will avoid surprises if you decide to move to the next release of long-term support.


We have free JDK 12 builds for Zulu Community Edition to help you test. Be sure to try them.


')

Source: https://habr.com/ru/post/446590/


All Articles