Recommended reading:
1. Overview of Features
The following are some of the new features introduced in Java 10. For a more detailed introduction to the new features of Java 10, please refer to here .
- Time-based release version control (JEP 322)
- Local variable type inference (JEP 286)
- Experimental JIT compiler (JEP 317)
- Application data sharing (JEP 310)
- Parallel Full GC for G1 (JEP 307)
- Clean up the garbage collector interface (JEP 304)
- Other Unicode language tag extensions (JEP 314)
- Root certificate (JEP 319)
- Thread local handshake (JEP 312)
- Heap allocation on alternate storage devices (JEP 316)
- Delete the native head generation tool-javah (JEP 313)
- Consolidate the JDK forest into a single repository (JEP 296)
- API changes
2. Time-based release version control (JEP 322)
2.1 The past and present of the release version number
Since Java changed hands, the string naming method of JDK release has been an intriguing topic.
In terms of the short version string format that you see when downloading the JDK, the number 7u40
before and u
after the version represents the first few revisions since the release of the JDK. However, Oracle has changed the rules to highlight security and the like major repair (Cirtical patch Updates) version , using an odd name, but modified for Bug fixes, API classes, the maintenance release , the use of an even number . (There is also a version number $MAJOR.$MINOR.$SECURITY
format to distinguish between bug fixes and API modifications)
For this reason, the existing JDK 6/7 release version has also been renamed. (Demo below)
Actual Hypothetical
Release Type long short
------------ ------------------------
Security 2013/06 1.7.0_25-b15 7u25
Minor 2013/09 1.7.0_40-b43 7u40
Security 2013/10 1.7.0_45-b18 7u45
Security 2014/01 1.7.0_51-b13 7u51
Minor 2014/05 1.7.0_60-b19 7u60
On the findings, the later re-named from 7u9
, 6u37
the beginning, you can count from parity to determine whether to repair major version; as for 7u40
later versions, major patched version is based on 5
a multiple of, the case of an even number plus one, and maintenance releases will be 20
Multiples of. Such a (not intuitive) naming method is standardized in JEP223 . (Released with JDK 9)
However, since the release of JDK 8, Oracle’s Java architect Mark Reinhold hopes that future Java releases can be based on time and will continue to release new versions with a half-year cycle, so that some useful small features can also be used by developers. , The JEP 223 specification is no longer applicable, and after the release of JDK 9, they once proposed a $YEAR.$MONTH
format based on the new version , but they received great opposition from the community. For this reason, they also proposed three alternatives, collecting each The opinion of the party. ( Https://goo.gl/7CA8B3 )
So, what is the next feature version of Java 8.3
? 1803
? Still 10
? The survey results show that most of the community supports it 10
, Stephen Colebourne also issued a request ( https://goo.gl/i5J44T), and said that Java is not like an operating system such as Ubuntu, which $YEAR.$MONTH
is not appropriate.
In the end, Oracle adopted $FEATURE.$INTERIM.$UPDATE.$PATCH
such a scheme and specified it in JEP 322 .
2.2 Interpretation of JEP 322 New Model
By adopting a time-based release cycle, Oracle has changed the version string scheme of the Java SE platform and JDK and related version information to apply to current and future time-based release models.
The new pattern of version numbers is:
$FEATURE.$INTERIM.$UPDATE.$PATCH
- FEATURE $ : Each counter
6
is incremented once a month, and based on the feature release version, for example: JDK 10, JDK 11. - $INTERIM : For non-functional versions that contain compatible bug fixes and enhancements but no incompatible changes, the counter will increase. Normally, this will be zero because there will not be any temporary releases for six months. This preserves future revisions to the published model.
- $UPDATE : The counter will increase for a compatible updated version that solves security issues, regressions, and bugs in newer features. This feature will be updated one month after the feature is released, and every three months thereafter. The April 2018 version is
JDK 10.0.1
, the July version isJDK 10.0.2
, and so on - $PATCH : The counter will increase for emergency release to solve serious problems.
And added a new API to get these counters programmatically:
Version version = Runtime.version();
version.feature();
version.interim();
version.update();
version.patch();
Now, let's take a look at the Java launcher that returns version information:
$ java -version
java version "10" 2018-03-20
Java(TM) SE Runtime Environment 18.3 (build 10+46)
Java HotSpot(TM) 64-Bit Server VM 18.3 (build 10+46, mixed mode)
The version number format is 10
because no other counter is zero. The release date has been added. It can be 18.3
understood as Year 2018 & 3rd Month, and the version 10 + 46
is the version 10
of the 46
version. For JDK 10.0.1
the hypothetical version 93
, the version will be 10.0.1 + 93
.
Therefore, for Java 9, the currently available version will be in 9.0.4
this format. As for the feature version released in March 2018, the new version will be provided by 10
the 9
month, that is 11
, JDK 11 is expected to be a long-term support version. Therefore, on the version string, LTS (long-term support) will also be displayed.
3. Local variable type inference (JEP 286)
3.1 Overview
One of the most obvious enhancements in JDK 10 is the use of initializers for type inference for local variables.
Before Java 9, we had to clearly write out the type of local variable and ensure that it is compatible with the initializer used to initialize it:
String message = "Good bye, Java 9";
In Java 10, this is how we can declare local variables:
@Test
public void whenVarInitWithString_thenGetStringTypeVar() {
var message = "Hello, Java 10";
assertTrue(message instanceof String);
}
We did not provide message
the specific type. Instead, we message
marked var
the type that the compiler would infer from message
the type of the initializer on the right . (In the above example message
is String
type)
Please note that this function is only applicable to local variables with initializers . It cannot be used for member variables, method parameters, return types, etc.-the initializer is necessary, otherwise, the compiler cannot infer its type.
This feature helps us reduce boilerplate code, such as:
Map<Integer, String> map = new HashMap<>();
Can now be rewritten as:
var idToNameMap = new HashMap<Integer, String>();
This also helps us focus on variable names, not variable types.
Another thing to pay attention to is var
not keywords -this ensures var
backward compatibility of programs used as function or variable names. var
Is a reserved type name, just like the int
same.
Finally, use var
will not increase runtime overhead, nor will it make Java a dynamically typed language . The variable type is still judged at compile time and cannot be changed later.
3.2 Analysis of illegal use of var
1. If there is no initialization program, it var
will not work:
var n; // error: cannot use 'var' on variable without initializer
2. If it is initialized to null, it will not work:
var emptyList = null; // error: variable initializer is 'null'
3. Not applicable to non-local variables:
public var word = "hello"; // error: 'var' is not allowed here
4. Lambda expressions require explicit types, so they cannot be used var
:
var p = (String s) -> s.length() > 10; // error: lambda expression needs an explicit target-type
5. The array initialization program also does not support:
var arr = { 1, 2, 3 }; // error: array initializer needs an explicit target-type
3.3 Guidelines for using var
In some cases, we can use it legally var
, but doing so is not a good idea.
For example, in the case of reduced code readability:
var result = obj.prcoess();
Here, although it can be used legally var
, it is difficult to understand the process()
returned type, which reduces the readability of the code.
java.net
There is an article on (OpenJDK official website) that introduces the writing guidelines of local variable type inference in Java . This article discusses the posture that should be paid attention to when using this feature and some good suggestions on how to use it.
In addition, var
another situation that is best avoided is in a stream with a longer pipeline:
var x = emp.getProjects.stream()
.findFirst()
.map(String::length)
.orElse(0);
In addition, using it var
with non-reference types may cause unexpected errors.
For example, if we will use it var
with anonymous class instances:
@Test
public void whenVarInitWithAnonymous_thenGetAnonymousType() {
var obj = new Object() {};
assertFalse(obj.getClass().equals(Object.class));
}
Now, if we try to assign another Object to it obj
, a compilation error occurs:
obj = new Object(); // error: Object cannot be converted to <anonymous Object>
This is because obj
the inferred type is not Object.
Fourth, the experimental JIT compiler (JEP 317)
Graal is a dynamic compiler written in Java and integrated with HotSpot JVM. It focuses on high performance and scalability. It is also the basis for the experimental Ahead-of-Time (AOT) compiler introduced in JDK 9.
JDK 10 enables the Graal compiler to be used as an experimental JIT compiler on Linux / x64 platforms.
To use Graal as a JIT compiler, use the following options on the Java command line:
-XX:+UnlockExperimentalVMOptions -XX:+UseJVMCICompiler
Please note that this is an experimental feature and we may not get better performance than existing JIT compilers.
For children's shoes who want to know more, please refer to Chris Seaton's speech: https://chrisseaton.com/truffleruby/jokerconf17/
(Ps: long text + special low-level warning...)
5. Application data sharing (JEP 310)
The class data sharing introduced in JDK 5 allows a group of classes to be preprocessed into a shared archive file, and then memory-mapped at runtime to reduce startup time, which can also be reduced when multiple JVMs share the same archive file Dynamic memory usage.
CDS only allows boot class loaders, restricting this feature to system classes. Application CDS (AppCDS) extends CDS to allow built-in system class loaders. Built-in platform class loader and custom class loader for loading archive classes. This makes it possible to use this feature for application classes.
We can use the following steps to use this feature:
1. Get the list of classes to be archived
The following command dumps the classes loaded by the HelloWorld application into hello.lst :
$ java -Xshare:off -XX:+UseAppCDS -XX:DumpLoadedClassList=hello.lst \
-cp hello.jar HelloWorld
2. Create AppCDS archive
The following command uses hello.lst as input to create hello.js A :
$ java -Xshare:dump -XX:+UseAppCDS -XX:SharedClassListFile=hello.lst \
-XX:SharedArchiveFile=hello.jsa -cp hello.jar
3. Use AppCDS to archive
The following command starts the HelloWorld application with hello.jsa as input :
$ java -Xshare:on -XX:+UseAppCDS -XX:SharedArchiveFile=hello.jsa \
-cp hello.jar HelloWorld
AppCDS is a commercial feature in Oracle JDK for JDK 8 and JDK 9. It is now open source and can be used publicly.
6. Parallel Full GC for G1 (JEP 307)
The G1 garbage collector is the default garbage collector since JDK 9. However, G1's Full GC uses a single-threaded mark-sweep-compact algorithm.
It has been changed to the parallel mark-sweep-compact algorithm in Java 10 , which effectively reduces the dead time during Full GC.
Seven, clean up the garbage collector interface (JEP 304)
This JEP is a future change. By introducing a common garbage collector interface, it improves the code isolation of different garbage collectors.
This change provides better modularity for the internal GC code. In the future, it will help to add new GCs without changing the existing code base, and it will also help to delete or retain previous GCs.
Official motivation explanation: ( Portal )
Currently, each garbage collector implementation consists
src/hotspot/share/gc/$NAME
of source files in its directory, such as G1 insrc/hotspot/share/gc/g1
, CMS insrc/hotspot/share/gc/cms
etc. However, some scattered information is scattered in HotSpot. For example, most GCs require certain barriers, which need to be implemented in the interpreters C1 and C2 at runtime. These obstacles are not included in the specific directory of the GC, but sharing the interpreter, rather than implementation, C1, and C2, the source code (typically a long guard -if
- ). The same problem applies to diagnostic codes, for example . This source code layout has several disadvantages:else
chains
MemoryMXBeans
For GC developers, implementing a new garbage collector requires knowledge about all these places and how to extend them to meet their specific needs.
For HotSpot developers who are not GC developers, where to find specific code snippets for a given GC can cause confusion.
It is difficult to exclude a specific garbage collector during construction. This
#define
INCLUD E_ALL_GCS
has long been a way to build a JVM with the only built-in serial collection, but this mechanism has become too rigid.A cleaner GC interface will make it easier to implement new collectors, make the code cleaner, and it will be easier to exclude one or more collectors at build time. Adding a new garbage collector should implement a set of well-documented interfaces, rather than figuring out all the things that need to be changed in HotSpot.
8. Other Unicode language label extensions (JEP 314)
This feature enhances java.util.Locale
and related APIs to implement other Unicode extensions for BCP 47 language tags. Starting with Java SE 9, the supported BCP 47 U language extensions are "ca" and "nu". The JEP will add support for the following additional extensions:
- cu (currency type)
- fw (first day of the week)
- rg (regional coverage)
- tz (time zone)
In order to support these additional extensions, the following various APIs have been changed to provide information based on U or additional extensions:
java.text.DateFormat::get*Instance
java.text.DateFormatSymbols::getInstance
java.text.DecimalFormatSymbols::getInstance
java.text.NumberFormat::get*Instance
java.time.format.DateTimeFormatter::localizedBy
java.time.format.DateTimeFormatterBuilder::getLocalizedDateTimePattern
java.time.format.DecimalStyle::of
java.time.temporal.WeekFields::of
java.util.Calendar::{getFirstDayOfWeek,getMinimalDaysInWeek}
java.util.Currency::getInstance
java.util.Locale::getDisplayName
java.util.spi.LocaleNameProvider
Nine, the root certificate (JEP 319)
The cacerts keystore (empty so far) is intended to contain a set of root certificates that can be used to establish trust in the certificate chains used by various security protocols.
As a result, in OpenJDK builds, critical security components such as TLS do not work by default.
With Java 10, Oracle open sourced the root certificate in the Oracle Java SE Root CA program to make OpenJDK builds more attractive to developers and reduce the differences between these builds and Oracle JDK builds.
10. Thread local handshake (JEP 312)
This is an internal feature used to improve JVM performance.
The handshake operation is a callback executed for each JavaThread when the thread is in a safe point state. The callback is executed by the thread itself or the VM thread while keeping the thread in a blocked state.
This feature provides a way to execute callbacks on threads without executing global VM safety points. It is possible to stop a single thread, instead of stopping all threads or not stopping threads , and at low cost.
11. Heap allocation on alternate storage devices (JEP 316)
The memory consumption of applications is increasing, and local cloud applications, in-memory databases, and streaming applications are all increasing. To satisfy these services, there are various memory architectures available. This feature enhances the HotSpot VM's ability to allocate Java object heaps on user-specified spare memory devices (such as NV-DIMM).
The goal of this JEP is an optional memory device that has the same semantics as DRAM (including the semantics of atomic operations), so it can be used for object heap instead of DRAM without changing the existing application code .
12. Delete the native head generation tool—javah (JEP 313)
This is a general change to remove javah
tools from the JDK . The tool function is added as part of JDK 8 javac
, which provides the javah
ability to write useless native header files at compile time .
Thirteen, merge the JDK forest into a single repository (JEP 296)
Over the years, various Mercurial repositories have been used for the JDK code base. Different repositories do provide some advantages, but they also have various operational disadvantages. As part of this change, many repositories of the JDK forest were merged into one repository to simplify and simplify development.
14. API changes
Java 10 added and removed APIs. Java 9 introduces enhanced deprecations, and some of the APIs are marked for removal in a future version.
So these APIs were deleted: you can find the deleted APIs here .
New APIs: 73 APIs have been added in Java 10. You can find and compare the added APIs here .
Let's take a look at the parts that are directly useful to us.
15. Improvements to unmodifiable collections
There are some changes related to unmodifiable collections in Java 10
copyOf()
java.util.List
, java.util.Map
And java.util.Set
both have a new static method copyOf(Collection)
.
It returns an unmodifiable copy of the given Collection:
jshell> var originList = new ArrayList<String>();
originList ==> []
jshell> originList.add("欢迎关注公众号:");
$2 ==> true
jshell> originList.add("我没有三颗心脏");
$3 ==> true
jshell> var copyList = List.copyOf(originList)
copyList ==> [欢迎关注公众号:, 我没有三颗心脏]
jshell> originList.add("获取更多精彩内容")
$5 ==> true
jshell> System.out.println(copyList)
[欢迎关注公众号:, 我没有三颗心脏]
jshell> copyList.add("获取更多精彩内容")
| 异常错误 java.lang.UnsupportedOperationException
| at ImmutableCollections.uoe (ImmutableCollections.java:73)
| at ImmutableCollections$AbstractImmutableCollection.add (ImmutableCollections.java:77)
| at (#7:1)
jshell>
toUnmodifiable()
java.util.Collectors
Get other methods to collect Stream into an unmodifiable List, Map, or Set:
@Test(expected = UnsupportedOperationException.class)
public void whenModifyToUnmodifiableList_thenThrowsException() {
List<Integer> evenList = someIntList.stream()
.filter(i -> i % 2 == 0)
.collect(Collectors.toUnmodifiableList());
evenList.add(4);
}
Any attempt to modify such a collection will result in a java.lang.UnsupportedOperationException
runtime exception.
16. Optinal new method orElseThrow()
java.util.Optional
, java.util.OptionalDouble
, java.util.OptionalInt
And java.util.OptionalLong
there is a new method orElseThrow()
, it does not accept any arguments, if any value does not exist, is thrown NoSuchElementException
:
@Test
public void whenListContainsInteger_OrElseThrowReturnsInteger() {
Integer firstEven = someIntList.stream()
.filter(i -> i % 2 == 0)
.findFirst()
.orElseThrow();
is(firstEven).equals(Integer.valueOf(2));
}
It get()
is synonymous with the existing method and is now its preferred alternative.