“This is the 20th day of my participation in the First Challenge 2022. For details: First Challenge 2022”

Hello, I’m looking at the mountains.

This article is part of a series of columns on the Journey to Java Progression.

Starting in 2017, the Java version update policy was changed from a new release every two years to a new release every six months to quickly validate new features and drive The development of Java. As you can see from the JVM Ecosystem Report 2021, nearly half of the development environment currently uses Java8, and nearly half of the people have migrated to Java11, with the release of Java17 expected to change that ratio.

Therefore, prepare a series with examples to illustrate the new features in each release.

An overview of the

Since Java10, the Java version has officially entered a semi-annual update rhythm. The update frequency is accelerated, and the update speed is fast.

Let’s take a look at some of the more interesting features that have been updated in Java10.

Local variable type inference

We all know that Java is a strongly typed language with strict type restrictions. If you want to define a variable, you must specify the type of the variable explicitly. But starting with Java10, we can use var to qualify variable types when defining local variables, and the Java compiler will infer the specific type from the value of the variable.

For example, we define a Map object:

Map<Integer, String> map = new HashMap<>();
Copy the code

Now we can write:

var idToNameMap = new HashMap<Integer, String>();
Copy the code

This feature is a taste of Java and opens up more possibilities for the Java language, making our code simpler and more focused on readability.

It is important to note that the new VAR does not turn Java into a dynamic language. At compile time, the compiler automatically inferred the type and converted it to a certain type, which does not change dynamically at run time.

Currently, var can only be used for local variables, and the right side of the equals sign must be the definition of a certain type, including: initialized instances, method calls, and anonymous inner classes.

Let’s go back to our example:

// The old way of writing
Map<Integer, String> map = new HashMap<>();

// Now you can write it like this
var idToNameMap = new HashMap<Integer, String>();
Copy the code

For parameter names, we can focus less on the type and more on the meaning of the parameter, which is also a requirement for writing readable code.

This also raises some requirements. If Lambda expressions are extremely long, use explicit types, otherwise it will get confusing.

Then there is the lack of intelligence in inferring types based on the most explicit inferences, such as:

var emptyList = new ArrayList<>();
Copy the code

The result of infering emptyList is ArrayList, not Listas we usually write it.

If it is an anonymous inner class, for example:

var obj = new Object() {};
Copy the code

In this case, obj.getClass() is not object.class and is the type of the anonymous inner class.

Therefore, although knife is good, but also good to use, careless use of easy injury.

Immutable set

Java9 provides implementations of immutable collections, and Java10 continues to expand. A collection is a container, and when passed to a method as a parameter, we don’t know whether the method will modify the elements in the container. With immutable collections, we have a degree of control (after all, when we modify the data of objects in the container, we don’t have that much control).

For immutable sets, we take the description of java.util.List (the other descriptions are similar) :

Unmodifiable Lists

The List.of and List.copyOf static factory methods provide a convenient way to create unmodifiable lists. The List instances created by these methods have the following characteristics:

  • They are unmodifiable. Elements cannot be added, removed, or replaced. Calling any mutator method on the List will always cause UnsupportedOperationException to be thrown. However, if the contained elements are themselves mutable, this may cause the List’s contents to appear to change.

  • They disallow null elements. Attempts to create them with null elements result in NullPointerException.

  • They are serializable if all elements are serializable.

  • The order of elements in the list is the same as the order of the provided arguments, or of the elements in the provided array.

  • They are value-based. Callers should make no assumptions about the identity of the returned instances. Factories are free to create new instances or reuse existing ones. Therefore, identity-sensitive operations on these instances (reference equality (==), identity hash code, and synchronization) are unreliable and should be avoided.

  • They are serialized as specified on the Serialized Form page.

A brief translation:

  • These collections are immutable, and elements cannot be added, subtracted, or replacedUnsupportedOperationExceptionThe exception. But, if the elements in the set are mutable, you can’t control them. For example, the element isAtomIntegerI can’t control what the values are, and the set just doesn’t change; If it isStringThat set is the whole invariant.
  • Don’t allownullThat will be thrownNullPointerException
  • A collection can be serialized if its elements are serializable
  • The order of the elements in the set is the order in which they are added
  • copyOfandofThe results returned from these methods may use pre-defined objects, such as empty collections, primitive collections, and so on. In other words, the same object is returned at different call locations. So don’t believe it= =,hashCodeDon’t lock it, either.

copyOf

List, java.util.Map, and java.util.Set have each added a copyOf static method to create ImmutableCollections, which will eventually become collections implementations defined in ImmutableCollections. This is similar to the of method defined in Java9.

For java.util.Map, java.util.Set, there is an optimization that returns the argument passed if it is itself an immutable collection, as follows:

static <E> Set<E> copyOf(Collection<? extends E> coll) {
    if (coll instanceof ImmutableCollections.AbstractImmutableSet) {
        return (Set<E>)coll;
    } else {
        return (Set<E>)Set.of(newHashSet<>(coll).toArray()); }}Copy the code

ToUnmodifiableList, toUnmodifiableSet, toUnmodifiableMap

Java10 nicely provides operations in Stream, so we create immutable collections directly. Such as:

Stream.of("1"."2"."3"."4"."5")
    .map(x -> "id: " + x)
    .collect(Collectors.toUnmodifiableList());
Copy the code

ToUnmodifiableList, toUnmodifiableSet, and toUnmodifiableMap are not much different from toList, toSet, or toMap in that they return immutable sets.

The Optional family added the orElseThrow method

The Optional family includes Optional, OptionalInt, OptionalLong, OptionalDouble. There was an orElseThrow(Supplier
exceptionSupplier) method is used to throw an exception defined in exceptionSupplier when no data is available.

We would write:

Stream.of("1"."2"."3"."4"."5")
    .map(x -> "id: " + x)
    .findAny()
    .orElseThrow(() -> new NoSuchElementException("No value present"));
Copy the code

The advantage is that we can customize our own exceptions and exception information. Sometimes we don’t care about specific exceptions and exception information, and this is where the new orElseThrow method in Java10 comes in handy:

Stream.of("1"."2"."3"."4"."5")
    .map(x -> "id: " + x)
    .findAny()
    .orElseThrow();
Copy the code

If the element is empty, NoSuchElementException is thrown.

Performance optimization

Java has been criticized for its poor performance, with a layer of virtual machines in between, allowing it to run across platforms and not performing as well as C. So Java has been putting a lot of effort into performance.

Let’s take a look at what optimization points are available in Java10.

G1 implements parallel Full GC algorithm

Starting with Java9, G1 has been normalized and is the default garbage collector. However, in Full GC, G1 still adopts the single-thread serial tag compression algorithm, so the STW time is relatively long. To Java10, Full GC implements a parallel tag compression algorithm that significantly reduces STW time.

Application Class Data Sharing (AppCDS)

Class-data Sharing (CDS) is a preprocessing method introduced in Java5 that can share a set of classes into an archive and load classes at runtime through memory mapping, which can reduce startup time. Sharing the same archive file across multiple JVMS simultaneously reduces dynamic memory footprint.

However, CDS has a limitation that it can only be used by Bootstrap ClassLoader, which limits the scope of the class. In Java10, this functionality was extended to the System ClassLoader (or Application ClassLoader), the built-in Platform ClassLoader, Or a custom class loader. This extends functionality to the application class.

To use this feature, there are three steps:

  1. Pack up and we’ll puthello.jarIn theHelloWorldClass to use the class added tohello.lstIn:
$java -Xshare:off -XX:+UseAppCDS -XX:DumpLoadedClassList=hello.lst \
   -cp hello.jar HelloWorld
Copy the code
  1. Creating the AppCDS archive is used nexthello.lstCreate an AppCDS file with the contents inhello.jsa:
$java -Xshare:dump -XX:+UseAppCDS -XX:SharedClassListFile=hello.lst \ -XX:SharedArchiveFile=hello.jsa -cp hello.jar
Copy the code
  1. Use AppCDS archive and finally usehello.jsaStart theHelloWorld:
$java -Xshare:on -XX:+UseAppCDS -XX:SharedArchiveFile=hello.jsa \ -cp hello.jar HelloWorld
Copy the code

Java-based JIT compiler Graal

Graal is a dynamic compiler written in Java that integrates with HotSpot JVM with a focus on high performance and scalability. Is the basis for the experimental AOT compiler introduced from JDK9.

In JDK10, Graal can be used as a JIT compiler on Linux/ X64 platforms. The following command is used to enable the function:

-XX:+UnlockExperimentalVMOptions -XX:+UseJVMCICompiler
Copy the code

It is important to note that this is an experimental feature, equivalent to a public beta phase, and may not perform as well as existing JIT compilers in some scenarios.

Support the container

Containerization is the current trend. In the past, due to the inability of the JVM to be container-aware, the deployment of multiple virtual machines on the same host caused problems such as memory footprint and CPU preemption. This has become a point of criticism at many conferences that the Java language is not suitable for the container era.

Now the JVM is aware of the container. It’s only Linux for now (so what, other platforms haven’t used it yet). This function is enabled by default. You can disable it manually if you do not want to use it:

-XX:-UseContainerSupport
Copy the code

We can also manually specify CPU cores:

-XX:ActiveProcessorCount=1
Copy the code

There are three more to control memory usage:

-XX:InitialRAMPercentage
-XX:MaxRAMPercentage
-XX:MinRAMPercentage
Copy the code

At present, this part can continue to improve, I believe it is only a matter of time.

Root Certificate Authentication

Since Java9, add the -cacerts parameter to keytool to view the root certificate currently managed by the JDK. In Java9, the cacerts directory is empty, which can cause a lot of inconvenience for developers. Starting with Java10, a default set of CA root certificates will be provided in the JDK.

The Cacerts keystore, part of the JDK, is intended to contain a set of root certificates that can be used to establish trust across certificate chains of various security protocols. Prior to Java10, cacerts keystores were empty, key security components such as TLS were disabled by default, and developers needed to manually add a set of root certificates to use these validations.

In Java10, Oracle opened up the source code for the root certificate to make OpenJDK builds more attractive to developers and reduce the differences between those builds and Oracle JDK builds.

Enable and delete functions

We can keep Java evolving to a certain extent.

Command-line tools and certain parameters

  • removejavahThis command is used to create C header files and resource files required by native methodsjavac -hAlternative.
  • removepolicytoolTool for creating and managing policy files. You can also use a text editor instead.
  • deletejava -XprofParameter, which is used to evaluate a running program and send the evaluation data to standard output. You can usejmapInstead.

Some of the API

The java.security.acl package is marked as expired, and the tag parameter forRemoval is true and will be removed in future releases. Currently, the functionality in this package has been replaced by java.security.Policy. The Certificate, Identity, IdentityScope, Signer tag parameter forRemoval in the java.security package is also true. These will be removed in subsequent releases.

Time-based release mode

Since Java10, Java has officially entered a semi-annual update rhythm. The major changes are as follows:

  1. Release a new set of features every 6 months;
  2. Long Term Support (LTS) will be supported for 3 years and other versions for 6 months;
  3. Java11 and Java17 are long-term support releases.
  4. using$FEATURE.$INTERIM.$UPDATE.$PATCHNaming mechanism:$FEATURE, increment 1 for each release, regardless of the specific release content;$INTERIM, intermediate release number, a release released in the middle of a major release that contains fixes and enhancements and does not introduce incompatibility changes;$PATCHUsed for quick patching.

At the end of the article to summarize

Java10 new features has been introduced in this paper, a complete list of features can be from openjdk.java.net/projects/jd… Look at it. This will be followed in a series of columns on the journey to Java progression.

Green hills never change, green waters always flow. See you next time.

Recommended reading

  • This article describes 24 operations for Java8 Stream Collectors
  • Java8 Optional 6 kinds of operations
  • Use Lambda expressions to achieve super sorting functions
  • Java8 Time Library (1) : Describes the time class and common apis in Java8
  • Java8 time library (2) : Convert Date to LocalDate or LocalDateTime
  • Java8 Time Library (3) : Start using Java8 time classes
  • Java8 time library (4) : check if the date string is valid
  • New features in Java8
  • New features in Java9
  • New features in Java10
  • Optimization of access control based on nested relationships in Java11
  • New features for Java11
  • New features in Java12

Hello, I’m looking at the mountains. Swim in the code, play to enjoy life. If this article is helpful to you, please like, bookmark, follow.