Easy to understand introduction to new functions of Java 13

Posted by jmarco on Tue, 04 Jan 2022 05:31:26 +0100

This article belongs to New Java features tutorial Series, which has been included in Github.com/niumoo/JavaNotes , like it, don't get lost.

Since Oracle adjusted the release rhythm of java version, the release of java version has become faster and faster. Although it is said that the Java version can be distributed by others, I use Java 8, but the functions of the new version of Java still need to be learned.

Java 13 has been released as early as September 2019. Although it is not a long supported version, it also brings many new functions.

Java 13 official download: https://jdk.java.net/archive/

Java 13 official documents: http://openjdk.java.net/projects/jdk/13/

New Java 13 features:

  1. JEP 350: dynamic CDS archiving
  2. JEP 351: ZGC, return unused memory (experimental)
  3. JEP 353: re implement Socket API
  4. JEP 354: Switch expression (second preview)
  5. JEP 355: text block (Preview)

Extension: This article belongs to New Java features tutorial Series, which will introduce the new functions of each version of Java. You can click to browse.

1. JEP 350 dynamic CDS archiving

When the JVM starts, one step is to load classes in memory. If there are multiple jars, the speed of loading the first jar is the slowest. This prolongs the startup time of the program. In order to reduce this time, Java 10 introduces the application class data sharing (CDS) mechanism, which can share the classes you want to share among programs, so that different Java processes can share this class to reduce the space occupied by this class and loading speed. However, the steps of using this function in Java 10 are cumbersome.

Extended reading: Introduction to new features of Java 10

AppCDS in Java 13 allows Java applications to dynamically archive at the end of program execution (if the JVM does not crash); the stored content includes all loaded application type classes and used class libraries, which do not exist in the default CDS archive.

Using this function is very simple. You only need to add startup parameters when the program starts.

# ArchiveClassesAtExit, dynamic archiving at the end of the program
bin/java -XX:ArchiveClassesAtExit=hello.jsa -cp hello.jar Hello
# SharedArchiveFile, starting with the specified archive
bin/java -XX:SharedArchiveFile=hello.jsa -cp hello.jar Hello

2. JEP 351: ZGC, return unused memory (experimental)

Before Java 13, although ZGC had very little pause time when cleaning memory, ZGC would not return memory to the operating system even if the memory had not been used for a long time, which was very unfriendly to those applications that paid great attention to memory occupation.

For example:

  • An on cloud container environment in which resources are paid by usage.

  • Although the application is idle for a long time, it occupies memory, resulting in a shortage of memory for other running programs.

The new function allows ZGC to return the memory unused for a long time to the operating system, which is very friendly to some users.

3. JEP 353: re implement Socket API

java.net.Socket and Java net. The ServerSocket class was introduced as early as Java 1.0. It is very difficult to maintain and debug the mixture of Java code and C language code; Moreover, there are concurrency problems in this implementation, and sometimes it is difficult to troubleshoot.

Therefore, a new implementation method is introduced in Java 13, and a new implementation NioSocketImpl is used to replace the old PlainSocketImpl implementation. Although the functions are the same, the old method will not be deleted in the current and future versions. Users can use - djdk at any time net. The useplainsocketimpl parameter switches back to the old implementation to be compatible with exceptions.

Writing a test class can find this change.

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class Test {
    public static void main(String[] args) {
        try (ServerSocket serverSocket = new ServerSocket(8000)){
            boolean running = true;
            while(running){
                Socket clientSocket = serverSocket.accept();
                //do something with clientSocket
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Run with Java 13 and track the loaded class through the parameter - XX:+TraceClassLoading. NioSocketImpl can be seen in the log.

➜  develop ./jdk-13.0.2.jdk/Contents/Home/bin/java -XX:+TraceClassLoading Test.java | grep SocketImpl
[0.699s][info   ][class,load] java.net.SocketImpl source: jrt:/java.base
[0.699s][info   ][class,load] java.net.SocketImpl$$Lambda$173/0x0000000800c37440 source: java.net.SocketImpl
[0.702s][info   ][class,load] sun.net.PlatformSocketImpl source: jrt:/java.base
[0.702s][info   ][class,load] sun.nio.ch.NioSocketImpl source: jrt:/java.base
[0.713s][info   ][class,load] sun.nio.ch.NioSocketImpl$FileDescriptorCloser source: jrt:/java.base

But in Java 12, it is not NioSocketImpl.

➜  develop ./jdk-12.0.2.jdk/Contents/Home/bin/java -XX:+TraceClassLoading Test.java | grep SocketImpl
[0.665s][info   ][class,load] java.net.SocketImpl source: jrt:/java.base
[0.665s][info   ][class,load] java.net.AbstractPlainSocketImpl source: jrt:/java.base
[0.665s][info   ][class,load] java.net.PlainSocketImpl source: jrt:/java.base
[0.665s][info   ][class,load] java.net.SocksSocketImpl source: jrt:/java.base
[0.666s][info   ][class,load] java.net.AbstractPlainSocketImpl$1 source: jrt:/java.base

4. JEP 354: Switch expression (second preview)

Why don't you want to use switch expressions? I think one of the reasons should be that the code of switch expression is not beautiful and elegant, or even wordy. Like the following example.

package com.wdbyte;

public class Java13Switch {
    public static void main(String[] args) {
      //The season of the month is output by importing the month
      System.out.println(switchJava12Before("march"));
    }
    public static String switchJava12Before(String month) {
        String reuslt = null;
        switch (month) {
            case "march":
            case "april":
            case "may":
                reuslt = "spring";
                break;
            case "june":
            case "july":
            case "august":
                reuslt = "summer";
                break;
            case "september":
            case "october":
            case "november":
                reuslt = "autumn";
                break;
            case "december":
            case "january":
            case "february":
                reuslt = "winter";
                break;
        }
        return reuslt;
    }
}

In Java 12, the switch has been improved so that it can be operated using cast L - > expression and can have return value, which makes the code more beautiful. However, it is a preview function in Java 12.

// The season of the month is output by importing the month
public static String switchJava12(String month) {
     return switch (month) {
        case "march", "april", "may"            -> "spring";
        case "june", "july", "august"           -> "summer";
        case "september", "october", "november" -> "autumn";
        case "december", "january", "february"  -> "winter";
        default -> "month erro";
    };
}

Extended reading: Introduction to new features of Java 12JEP 325: Switch expression

Now, in Java 13, the switch expression is enhanced, and the yield keyword is added for the return value. Compared with break, the semantics is more clear.

public static String switchJava13(String month) {
    return switch (month) {
        case "march", "april", "may":
            yield "spring";
        case "june", "july", "august":
            yield "summer";
        case "september", "october", "november":
            yield "autumn";
        case "december", "january", "february":
            yield "winter";
        default:
            yield "month error";
    };
}

5. JEP 355: text block (Preview)

Before that, if we assign a JSON to a string:

String content = "{\n"
    + "    \"upperSummary\": null,\n"
    + "    \"sensitiveTypeList\": null,\n"
    + "    \"gmtModified\": \"2011-08-05 10:50:09\",\n"
    + "    \"lowerGraph\": null,\n"
    + "    \"signature\": \"\",\n"
    + "    \"appName\": \"xxx\",\n"
    + "    \"lowerSummary\": null,\n"
    + "    \"gmtCreate\": \"2011-08-05 10:50:09\",\n"
    + "    \"type\": \"CALL\",\n"
    + "    \"name\": \"xxxx\",\n"
    + "    \"subType\": \"yyy\",\n"
    + "    \"id\": 1,\n"
    + "    \"projectId\": 1,\n"
    + "    \"status\": 1\n"
    + "}";

Finally, you don't have to write ugly long strings. From Java 13, you can define strings in the way of text blocks.

String content2 = """
        {
        "upperSummary": null,
        "sensitiveTypeList": null,
        "gmtModified": "2011-08-05 10:50:09",
        "lowerGraph": null,
        "signature": "",
        "appName": "xxx",
        "lowerSummary": null,
        "gmtCreate": "2011-08-05 10:50:09",
        "type": "CALL",
        "name": "xxxx",
        "subType": "yyy",
        "id": 1,
        "projectId": 1,
        "status": 1
    }
                 """;

However, this is a preview function. If you use it in Java 13, you need to turn on the preview function manually. This function is officially released in Java 15.

If you want to try, you can download the latest version and have a good time.

reference resources

  1. http://openjdk.java.net/projects/jdk/13/
  2. https://nipafx.dev/java-application-class-data-sharing/
  3. https://www.wdbyte.com/2020/02/jdk/jdk12-feature/
  4. https://mkyong.com/java/what-is-new-in-java-13/
  5. New Java features tutorial

Related reading

Hello world 😃

I'm Alan, a procedural ape. I'm Lang with a clear moon and a clear wind. I'm a technical tool person who moves bricks every day.

If you want to subscribe, you can follow The official account is "unread code". , or Unread code blog , or Add wechat (wn8398).

This article has also been sorted to GitHub.com/niumoo/JavaNotes Welcome, Star.

Topics: Java