JavaRush /Java Blog /Random EN /From 8 to 13: A complete overview of Java versions. Part ...

From 8 to 13: A complete overview of Java versions. Part 2

Published in the Random EN group
This article is the second part of my review of innovations in Java versions 8-13. The first part is here . Without further ado, let's move on: to September 25, 2018, when the new JDK was released:

Java 11

From 8 to 13: a complete overview of Java versions.  Part 2 - 1

var (in lambda)

From now on, we can specify the types of lambda parameters or omit them when writing a lambda expression (implicitly typed lambda expressions):
Function<String, String> append = (var string) -> string + " Text";
String appendedString = append.apply("Some");
System.out.println(appendedString);
You can also add annotations to lambda parameters without having to write the full variable type name:
Function<String, String> append = (@NonNull var string) -> string + " Text";

Z(ZGC)

ZGC is a new garbage collector that doesn't work. It allocates new memory but never restarts it. ZGC promises to manage large amounts of memory with high throughput and low latency (ZGC is only available on 64-bit platforms). Reference Coloring - ZGC uses 64-bit pointers with a technique called pointer coloring. Colored pointers store additional information about objects on the heap. When memory becomes fragmented, this helps avoid performance degradation when the GC needs to find room for a new allocation. Garbage collection using ZGC consists of the following steps:
  1. world stops: we look for starting points to reach objects on the heap (such as local variables or static fields);
  2. intersection of object graphs starting from root links. We mark each object we reach (ZGC walks through the object graph and examines the colored markers, marking available objects);
  3. handling some edge cases, such as weak links;
  4. moving living objects, freeing large areas of the heap to speed up allocation.
  5. when the move phase begins, ZGC splits the heap into pages and works one page at a time;
  6. The ZGC finishes the movement of any roots and the rest of the movement occurs.
This topic is very complex and confusing. A detailed discussion would require a separate article, so I’ll just leave it here:

Epsilon GC

Epsilon is a garbage collector that handles memory allocation but does not implement any real memory recovery mechanism. Once the available Java heap is exhausted, the JVM will shut down. That is, if you start creating an object in an infinite array without binding to a reference with this garbage collector, the application will crash with an OutOfMemoryError (and if with any other, it will not, since it will clean up objects without references). Why is it needed? Here's why:
  1. Performance testing.
  2. Memory pressure testing.
  3. Testing the VM interface.
  4. Extremely short work.
  5. Last drop latency improvements.
  6. Last drop throughput improvements.
Useful links: Other innovations:
  1. ByteArrayOutputStreamgot a method void writeBytes(byte [])that writes all the bytes from the argument to OutputStream.
  2. FileReaderand FileWritergot new constructors that allow you to specify Charset.
  3. Pathgrabbed two new methods, of(String, String [])returns Pathfrom a string argument a path or sequence of strings that when combined form a path string and of(URI): returns Path from a URI.
  4. Pattern— received a method asMatchPredicate()that checks whether a given input string matches a given pattern (whether it allows you to create a predicate using a regular expression so that you can, for example, filter data in stream).
  5. StringI picked up many useful methods, such as:
    • String strip(): will return us a string that is this string, with all spaces at the beginning and end of the string removed (similar to trim(), but defines spaces differently);
    • String stripLeading(): will return us the string that is this string, removing any leading spaces from the string;
    • String stripTrailing(): will return us the string that is this string, removing any spaces at the end of the string;
    • Stream lines(): will return us Streamfrom String, extracted from this string, separated by line separators;
    • String repeat(int): will return us a string that is a concatenation of this string, repeated a number of times.
    • boolean isBlank(): will return true if the string is empty or contains only spaces, false otherwise.
  6. Thread— methods destroy() and stop(Throwable) have been removed.
  7. Filesgot a number of new methods:
    • String readString(Path): reads all data from a file into a string, while decoding from bytes to characters using UTF-8 encoding;
    • String readString(Path, Charset): same as in the method above, with the difference that decoding from bytes to characters occurs using the specified Charset;
    • Path writeString (Path, CharSequence, OpenOption []): Writes a sequence of characters to a file. Characters are encoded into bytes using UTF-8 encoding;
    • Path writeString(Path, CharSequence,Charset, OpenOption []): Same method as above, only characters are encoded into bytes using the encoding specified in Charset.
These were the most interesting API innovations (in my humble opinion), here are a couple of materials for a more detailed review:

Java 12

Six months pass and we see the next stage in the evolution of Java. So, it’s time to take out a shovel of knowledge and dig. From 8 to 13: a complete overview of Java versions.  Part 2 - 2

Update G1

The following improvements have been made for G1:
  1. Reclaim unused allocated memory

    In Java heap memory there is such a thing as unused memory (or in other words, inactive). In Java 12 they decided to fix this problem, now:

    • G1 returns memory from the heap in a full GC or during a parallel loop; G1 tries to prevent a full GC and starts a parallel loop based on the heap allocation. We will have to force G1 to return memory from the heap.

    This improvement focuses on performance by automatically returning memory from the heap to the OS when G1 is not in use.

  2. Aborting mixed collections when pause time is exceeded

    G1 uses an analysis engine to select the amount of work required for garbage collection. It collects live objects without stopping after defining the set and starting the cleanup. This causes the garbage collector to exceed its pause time target. Actually, this problem is solved by the improvement, since if the time required to complete the next step is beyond reasonable limits, this step can be interrupted.

Microbenchmark

Java 12 introduced microbenchmarking tests so that JVM performance can be easily tested using existing benchmarks. This would be very useful for anyone who wants to work on the JVM itself. The added tests are created using Java Microbenchmark Harness (JMH). These tests allow for continuous performance testing on the JVM. JEP 230 proposes the introduction of approximately 100 tests, with new tests introduced as new versions of Java are released. Here is an example of the tests being added .

Shenandoah

This is a garbage collection (GC) algorithm that aims to guarantee low response times (lower limit is 10-500 ms). This reduces GC pause time when doing cleanup work concurrently with running Java threads. In Shenandoah, the pause time is independent of the heap size. This means that the pause time will be the same regardless of the size of your heap. This is an experimental feature and is not included in the standard (Oracle) build of OpenJDK.

Improve Switch

Java 12 has improved Switch expressions for pattern matching. A new syntax L → was introduced. Here is a list of the key points of the new switch :
  1. The new syntax eliminates the need for a break statement to prevent errors.
  2. Switch expressions no longer fail.
  3. Additionally, we can define multiple constants in a single label.
  4. default case is now required in switch expressions.
  5. break is used in Switch expressions to return values ​​from the register itself (in fact, a switch can return values).
Let's look at this as an example:
var result = switch (someDay) {
  case "M", "W", "F" -> "MWF";
  case "T", "TH", "S" -> "TTS";
  default -> {
      if(someDay.isEmpty())
            break "Please insert a valid day.";
      else
            break "Looks like a Sunday.";
  }
};
Definitive Guide To Switch Expressions In Java 13 Other new features:
  1. String:

    transform(Function f)- Applies the provided function to a string. The result may not be a string.
    indent(int x)— adds x spaces to the string. If the parameter is negative, then this number of leading spaces will be removed (if possible).

  2. Files- grabbed a method like mismatch(), which, in turn, finds and returns the position of the first mismatched byte in the contents of two files, or -1L if there is no mismatch.

  3. A new class has appeared -CompactNumberFormat for formatting a decimal number in a compact form. An example of this compact form is 1M instead of 1,000,000. Thus, only two two are required instead of nine characters.

  4. There is also a new one enum , NumberFormatStylewhich has two values ​​- LONG and SHORT.

  5. InputStream got the method skipNBytes(long n) : skip the nth number of bytes from the input stream.

Interesting Java 12 links:

Java 13

The world does not stand still, it moves, it develops, just like Java - Java 13. From 8 to 13: a complete overview of Java versions.  Part 2 - 3

Text block

Java has always suffered a bit when it comes to defining strings. If we need to define a line with a space, a line break, a quote or something else, this caused some difficulties, so we had to use special characters: for example, \n for a line break, or escape some of the line itself. This significantly reduces the readability of the code and takes extra time when writing such a line. This becomes especially noticeable when writing strings that display JSON, XML, HTML, etc. As a result, if we want to write a small Json, it will look something like this:
String JSON_STRING = "{\r\n" + "\"name\" : \"someName\",\r\n" + "\"site\" : \"https://www.someSite.com/\"\r\n" + "}";
And then Java 13 comes onto the scene and offers us its solution in the form of triple double quotes before and after the text (which they called text blocks). Let's look at the previous json example using this innovation:
String TEXT_BLOCK_JSON = """
{
    "name" : "someName",
    "site" : "https://www.someSite.com/"
}
""";
Much simpler and clearer, isn’t it? StringThree new methods were also added, respectively, for managing these blocks:
  • stripIndent(): Removes random spaces from a string. This is useful if you're reading multiline strings and want to apply the same kind of random whitespace exclusion that occurs with an explicit declaration (essentially simulating the compiler to remove random whitespace);
  • formatted(Object... args ): similar to format(String format, Object... arg), but for text blocks;
  • translateEscapes(): Returns a string with escape sequences (such as \r) translated to the corresponding Unicode value.

Improve Switch

Switch expressions were introduced in Java 12, and 13 refines them. In 12 you define return values ​​using break. In 13, the return value was replaced with yield. Now the switch expression that we had in the Java 12 section can be rewritten as:
var result = switch (someDay) {
  case "M", "W", "F" -> "MWF";
  case "T", "TH", "S" -> "TTS";
  default -> {
      if(someDay.isEmpty())
          yield "Please insert a valid day.";
      else
          yield "Looks like a Sunday.";
  }
};
Although it was normal for us programmers already familiar with Java to accept break, it was nevertheless quite strange. What is break true trying to tell me? The new (relatively new) yield keyword is clearer and may appear in other places in the future where values ​​are returned. For those who are deeply interested in this topic, I recommend that you familiarize yourself with these materials:

Dynamic CDS Archives

CDS - Class-Data Sharing. Allows you to package a set of commonly used classes into an archive that can later be loaded by multiple JVM instances. Why do we need this? The fact is that in the process of loading classes, the JVM does quite a lot of resource-intensive actions, such as reading classes, storing them in internal structures, checking the correctness of the read classes, searching for and loading dependent classes, etc., and only after all this the classes are ready to work. Understandably, a lot of resources are wasted, since JVM instances can often load the same classes. For example String, LinckedList, Integer. Well, or classes of the same application, and all of these are resources. If we performed all the necessary steps just once and then placed the redesigned classes in an archive that could be loaded into the memory of several JVMs, this could significantly save memory space and reduce application startup time. Actually, CDS makes it possible to create just such an archive. Java 9 only allowed system classes to be added to the archive. Java 10 - include application classes in the archive. The creation of such an archive consists of:
  • creating a list of classes loaded by the application;
  • creating a much-needed archive with the classes we found.
The innovation in Java 13 improves CDS so that it can create an archive when the application terminates. This means that the two steps above will now be combined into one. And one more important point: only classes that were loaded while the application was running will be added to the archive. In other words, those classes that are still contained in application.jar, but for some reason were not loaded, will not be added to the archive.

Update Socket API

The Socket API ( java.net.Socket and java.net.ServerSocket ) is essentially an integral part of Java since its inception, but sockets have never been updated in the last twenty years. Written in C and Java, they were very, very bulky and difficult to maintain. But Java 13 decided to make its own adjustments to this whole matter and replaced the base implementation. Now, instead of PlainSocketImpl, the provider interface is replaced with NioSocketImpl . This new coded implementation is based on the same back-end infrastructure as java.nio . Essentially the class uses the java.util.concurrent buffer cache and locking mechanism (which are segment-based) rather than synchronized methods. It no longer requires native code, making it easier to port to different platforms. Still, we have a way to return to using PlainSocketImpl , but from now on NioSocketImpl is used by default .

Memory Return for ZGC

As we remember, the Z garbage collector was introduced in Java 11 as a low-latency garbage collection mechanism so that the GC pause never exceeds 10 ms. But at the same time, unlike other virtual GC HotSpots, such as Shenandoah and G1, it could return unused dynamic memory to the OS. This modification adds this J capability to ZGC. Accordingly, we get reduced memory footprint along with improved performance, and ZGC now returns uncommitted memory to the operating system by default until the specified minimum heap size is reached. One more thing: ZGC now has a maximum supported heap size of 16 TB. Previously, 4TB was the limit. Other innovations:
  1. javax.security- added a property jdk.sasl.disabledMechanismsto disable SASL mechanisms.
  2. java.nio- a method has been added FileSystems.newFileSystem (Path, Map <String,?>)- respectively, to create a new file.
  3. Classes java.nionow have absolute (as opposed to relative) getand set-methods. They, like the base abstract class Buffer, include a method slice()for retrieving part of the buffer.
  4. Added javax.xml.parsersmethods for instantiating DOM and SAX factories (with namespace support).
  5. Unicode support has been updated to version 12.1.
Interesting links on Java 13:

Results

We could go over the announced innovations in Java 14, but since it will see the light quite soon - JDK 14 is scheduled for release on March 17, 2020, it would be best to conduct a separate, full review of it immediately after its release. I would also like to draw your attention to the fact that in other programming languages ​​with long breaks between releases, such as Python 2–3, there is no compatibility: that is, if the code is written in Python 2, you will need to work hard translating it to 3. Java is special in this regard because it is extremely backward compatible. This means that your Java 5 or 8 program is guaranteed to run on a Java 8-13 virtual machine—with a few exceptions that you don't need to worry about for now. It is clear that this does not work the other way around: for example, if your application uses Java 13 functions that are simply not available in the Java 8 JVM. That's all for me today, respect to those who have read to this point)) From 8 to 13: a complete overview of Java versions.  Part 2 - 5
Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION