【JAVA拾遗】Java8新特性合辑
文章目录
- 【JAVA拾遗】Java8新特性合辑
- 0. 逼逼
- [--/--]126 Lambda Expressions & Virtual Extension Methods
- [--/--]138 Autoconf-Based Build System
- [--/--]160 Lambda-Form Representation for Method Handles
- [--/--]161 Compact Profiles
- [--/--]162 Prepare for Modularization
- [--/--]164 Leverage CPU Instructions for AES Cryptography
- [--/--]174 Nashorn JavaScript Engine
- [--/--]176 Mechanical Checking of Caller-Sensitive Methods
- [--/--]179 Document JDK API Support and Stability
- [vm/--]142 Reduce Cache Contention on Specified Fields
- [vm/gc]122 Remove the Permanent Generation
- [vm/gc]173 Retire Some Rarely-Used GC Combinations
- [vm/rt]136 Enhanced Verification Errors
- [vm/rt]147 Reduce Class Metadata Footprint
- [vm/rt]148 Small VM
- [vm/rt]171 Fence Intrinsics
- [core/--]153 Launch JavaFX Applications
- [core/lang]101 Generalized Target-Type Inference
- [core/lang]104 Annotations on Java Types
- [core/lang]105 DocTree API
- [core/lang]106 Add Javadoc to javax.tools
- [core/lang]117 Remove the Annotation-Processing Tool (apt)
- [core/lang]118 Access to Parameter Names at Runtime
- [core/lang]120 Repeating Annotations
- [core/lang]139 Enhance javac to Improve Build Speed
- [core/lang]172 DocLint
- [core/libs]103 Parallel Array Sorting
- [core/libs]107 Bulk Data Operations for Collections
- [core/libs]109 Enhance Core Libraries with Lambda
- [core/libs]112 Charset Implementation Improvements
- [core/libs]119 javax.lang.model Implementation Backed by Core Reflection
- [core/libs]135 Base64 Encoding & Decoding
- [core/lib]149 Reduce Core-Library Memory Usage
- [core/lib]150 Date & Time API
- [core/libs]155 Concurrency Updates
- [core/libs]170 JDBC 4.2
- [core/libs]177 Optimize java.text.DecimalFormat.format
- [core/libs]178 Statically-Linked JNI Libraries
- [core/libs]180 Handle Frequent HashMap Collisions with Balanced Trees
- [core/i18n]127 Improve Locale Data Packaging and Adopt Unicode CLDR Data
- [core/i18n]BCP 47 Locale Matching
- [core/i18n]133 Unicode 6.2
- [core/net]184 HTTP URL Permissions
- [core/sec]113 MS-SFU Kerberos 5 Extensions
- [core/sec]114 TLS Server Name Indication (SNI) Extension
- [core/sec]115 AEAD CipherSuites
- [core/sec]121 Stronger Algorithms for Password-Based Encryption
- [core/sec]123 Configurable Secure Random-Number Generation
- [core/sec]124 Enhance the Certificate Revocation-Checking API
- [core/sec]129 NSA Suite B Cryptographic Algorithms
- [core/sec]130 SHA-224 Message Digests
- [core/sec]131 PKCS#11 Crypto Provider for 64-bit Windows
- [core/sec]140 Limited doPrivileged
- [core/sec]166 Overhaul JKS-JCEKS-PKCS12 Keystores
- [web/jaxp]185 Restrict Fetching of External XML Resources
0. 逼逼
Java9
去年正式发布,今天偶然在oracle
官网发现Java10
,然而对于Java8
的新特性还没有一个完全的了解和应用,大多数了解也只是停留在语法的基础上,现在把这些特性做个合辑,如今工作环境使用的是Java8
,方便查阅。
完全按照JDK 8 Features列表顺序记录,一些不明白或者没用到的特性暂时只做记录不深入研究。
[–/--]126 Lambda Expressions & Virtual Extension Methods
Add lambda expressions (closures) and supporting features, including method references, enhanced type inference, and virtual extension methods, to the Java programming language and platform.
包含两个部分:lambda
表达式和虚拟扩展方法。前者让代码看起来更简洁(难懂[滑稽]),后者让接口修改保持向后兼容变得方便。只要使用Java8
都不可避免地会用到lambda
表达式,在函数式接口中使用的最多,IDEA
还会针对可以使用lambda
表达式而没有使用的代码给出建议,多用用就会了:Java8 lambda表达式10个示例
public static void main(String[] args){
Arrays.asList(1,2,3,4).forEach(integer -> System.out.println(integer + 1));//2 3 4 5
}
格式如下
(params) -> expression
(params) -> statement
(params) -> { statements }
虚拟扩展方法主要是针对接口的兼容解决办法,比如Iterable
接口的forEach()
方法,这个方法在Java7
是没有的,假如要把Java8
的代码编译成Java7
可以执行怎么办?可以给这个forEach()
接口添加一个默认的实现,在编译成低版本的可执行文件的时候直接编译默认的实现,这样的方法被关键字default
修饰。
同样的,实际开发中,如果某一个接口被很多模块实现,如果给这个接口添加一个方法,那一定会是惊天动地的,所有实现了这个接口的模块全部要做更改,这时候虚拟扩展方法就派上用场了。
public class VirtualExtensionMethods {
public static void main(String[] args){
A a = new A();
a.a();//A.a()
a.b();//default b()
B b = new B();
b.a();//B.a()
b.b();//B.b()
}
interface If{
void a();
default void b(){
System.out.println("default b()");
}
}
static class A implements If {
@Override
public void a() {
System.out.println("A.a()");
}
}
static class B implements If {
@Override
public void a() {
System.out.println("B.a()");
}
@Override
public void b() {
System.out.println("B.b()");
}
}
}
这让虚拟扩展方法和abstract class
有点相似,似乎两者变得更加模糊了。其实不然,接口依然代表like-a
,抽象类依然代表is-a
,接口依然不能写构造方法,接口还是不能有自己的属性,接口还是不能有final
和private
方法声明等等,在Java8
里接口和抽象类依然发挥着自己的作用,只是为接口兼容提供了一种更方便的解决方案。
[–/--]138 Autoconf-Based Build System
Introduce autoconf (./configure-style) build setup, refactor the Makefiles to remove recursion, and leverage JEP 139: Enhance javac to Improve Build Speed.
[–/--]160 Lambda-Form Representation for Method Handles
Improve the implementation of method handles by replacing assembly language paths with an optimizable intermediate representation and then refactoring the implementation so that more work is done in portable Java code than is hardwired into the JVM.
[–/--]161 Compact Profiles
Define a few subset Profiles of the Java SE Platform Specification so that applications that do not require the entire Platform can be deployed and run on small devices.
这个功能主要用于精简jre
,假设需要在一个小设备上运行java
程序,但是并没有足够的空间存储整个jre
,而且我们知道很多java
程序并不需要整个jre
包,因此可以只拷贝必要的jar
包到设备上就可以了。默认的profile
有四个:compact1/compact2/compact3/FULL JRE
,他们分别包含的包信息:Java SE Embedded 8 Compact Profiles Overview
通常情况是:
- 先正常开发,或者先规定一个
profile
,比如compact1
,只能使用这个profile
下的包; - 使用
jdeps
工具检查用到了哪个级别的profile
,如果不能超出规定的profile
,那就得改代码; - 使用
jrecreate
创建空间占用更小的jre
,注意jrecreate
工具只在ORACLE JAVA SE EMBEDDED里才有的; - 使用精简过后
jre
运行jar
。
下面是一个例子。
首先写好一个java hello world
:
public static void main(String[] args){
System.out.println("Hello World!");
}
然后打包成hello_world.jar
,IDEA
·Eclipse
·Maven
都有各自的打包工具或插件,然后分析profile
:
jdeps -P hello_world.jar
#output>>>>>>>>>>
hello_world.jar -> /usr/local/java/java8/jre/lib/rt.jar (compact1)
com.chenlei.hello (hello_world.jar)
-> java.io compact1
-> java.lang compact1
#output>>>>>>>>>>
说明只用到了compact1
,只需要compact1
级别的jre
就足以运行这个jar
。
然后下载Oracle Java SE Embedded Version 8 Update 161
# 解压
tar -zvxf ejdk-8u161-linux-i586.tar.gz
# 创建精简版jre
cd ejdk1.8.0_161/bin
sh jrecreate.sh --profile compact1 --dest /tmp/compact1Jre
#output>>>>>>>>>>>
Building JRE using options Options {
ejdk-home: /usr/local/ejava8/ejdk1.8.0_161/bin/..
dest: /tmp/compact1Jre
target: linux_i586
vm: minimal
runtime: compact1 profile
debug: false
keep-debug-info: false
no-compression: false
dry-run: false
verbose: false
extension: []
}
#output>>>>>>>>>>>
更多参数:Create Your JRE with jrecreate
最后的jre
居然只有11M
,将jre
和jar
包考到目标设备,文件结构如下:
jar
|_hello_world.jar
jre
|-bin
|-lib
|_...
# 试试执行
jre/bin/java -jar jar/hello_world.jar
#output>>>>>>>>>
Hello World!
#output>>>>>>>>>
这在嵌入式系统或者小设备上很有用,一个简单的程序不需要把100+M
的jre
打包过去,还是非常有用的。
[–/--]162 Prepare for Modularization
Undertake changes to smooth the eventual transition to modules in a future release, provide new tools to help developers prepare for the modular platform, and deprecate certain APIs that are a significant impediment to modularization.
只是为Java9
的模块化做了一些准备工作,比如deprecate
一些API
。
[–/--]164 Leverage CPU Instructions for AES Cryptography
Improve the out-of-box AES Crypto performance by using x86 AES instructions when available, and by avoiding unnecessary re-expansion of the AES key.
[–/--]174 Nashorn JavaScript Engine
Design and implement a new lightweight, high-performance implementation of JavaScript, and integrate it into the JDK. The new engine will be made available to Java applications via the existing javax.script API, and also more generally via a new command-line tool.
这个Javascript
引擎就好玩了,Java
直接调用Js
脚本,Js
脚本可以是动态的,同时Js
中也可以使用各种Java
的类和方法,无论是Js
还是Java
感觉都有无限可能。
首先是jjs
工具,直接敲入jjs
命令可以得到一个js shell
:
jjs
iis> var sum=function(a,b){return a+b};print(sum(1,2));
jjs> 3
jjs> exit();
这时不得不感叹,Java
宁愿给一个Js
引擎做个Shell
,也不愿意给Java
做个Shell
,每次我要验证一段非常简单的代码都得写个main()
方法,不过Java9
就有一个专门的jshell
了,可以直接执行Java
代码,美滋滋。
然后是用jjs
命令执行js
脚本文件,先写个hello.js
:
var array = [1,2,3,4,5,6,7,8,9,10];
var arrayFilter = array.filter(function(i){
return i >= 5;
},0);
print(arrayFilter);
var sum = arrayFilter.reduce(function (acc,next){
return acc + next;
},0);
print(sum);
使用jjs
命令执行脚本:
jjs hello.js
#output>>>>>>>
5,6,7,8,9,10
45
#putput>>>>>>>
在Js
中使用Java
代码或功能,修改hello.js
:
//简单使用
print(java.lang.System.currentTimeMillis());
print(java.lang.System.getProperty("profile"));
//集合
var array = new java.util.ArrayList();
[1, 2, 3, 4].forEach(function(item) {
array.add(item);
});
//Stream API
var arrayFilter = array.stream().filter(function(i){return i >=2;}).collect(java.util.stream.Collectors.toList());
print(arrayFilter);
print(arrayFilter.getClass());
//实现接口
var ObjectType = Java.type("java.lang.Object");
var Comparable = Java.type("java.lang.Comparable");
var Serializable = Java.type("java.io.Serializable");
var MyExtender = Java.extend(
ObjectType, Comparable, Serializable);
var instance = new MyExtender({
someInt: 0,
compareTo: function(other) {
var value = other["someInt"];
if (value === undefined) {
return 1;
}
if (this.someInt < value) {
return -1;
} else if (this.someInt == value) {
return 0;
} else {
return 1;
}
}
});
print(instance instanceof Comparable);
print(instance instanceof Serializable);
print(instance.compareTo({ someInt: 10 }));
print(instance.compareTo({ someInt: 0 }));
print(instance.compareTo({ someInt: -10 }));
//读文件
var file = new java.io.File("/etc/hosts");
var bufferedReader = new java.io.BufferedReader(new java.io.FileReader(file));
var line;
while((line = bufferedReader.readLine()) != null){
print(line);
}
使用jjs
命令执行脚本(-D
可以指定properties
):
jjs hello.js -Dprofile=pp
#output>>>>>>>
1522489587353
1522490564583
pp
[2, 3, 4]
class java.util.ArrayList
true
true
-1
0
1
# 127.0.0.1 localhost
# ::1 localhost
#output>>>>>>>
当我看到输出的时候简直惊呆了,我的天,那Js
不是可以为所欲为了?好像还真是的。
再来看看Java
中执行Js
脚本:
package com.chenlei.hello;
import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import java.io.FileNotFoundException;
import java.io.FileReader;
/**
* Created by IntelliJ IDEA
*
* @author chenlei
* @date 2018/3/31
* @time 18:16
* @desc NashornScriptEngine
*/
public class NashornScriptEngine {
public static void main(String[] args) throws ScriptException, NoSuchMethodException, FileNotFoundException {
//简单使用
ScriptEngineManager engineManager = new ScriptEngineManager();
ScriptEngine engine = engineManager.getEngineByName("nashorn");
engine.eval("function sum(a,b){return a+b;}");
System.out.println(engine.eval("sum(1,2);"));
//使用invocable调用js里面的函数
Invocable invocable = (Invocable) engine;
System.out.println(invocable.invokeFunction("sum",1,3));
//将js的方法映射到java接口
Add adder = invocable.getInterface(Add.class);
System.out.println(""+ adder.sum(2,3));
//执行js文件
engine.eval(new FileReader("F:\\JavaWorkarea\\hello_world\\src\\main\\resources\\hello.js"));
}
public interface Add{
int sum(int a, int b);
}
}
//output
/*
3.0
4.0
5
1522491865022
null
[2, 3, 4]
class java.util.ArrayList
true
true
-1
0
1
# 127.0.0.1 localhost
# ::1 localhost
*/
还有一个很棒的特点是脚本支持heredocs
和shell invocations
,前者可以简单理解为能用EL
表达式取值,后者可以执行Shell
命令;前者需要加-scripting
选项,后者不需要,先修改hello.js
:
var data = {
foo:"bar",
time: new Date()
};
print ("foo = ${data.foo}\ntime = ${data.time}");
var hostname =`hostname`;
print(hostname);
使用jjs -scripting
命令执行脚本:
jjs -scripting hello.js
#output>>>>>>>
foo = bar
time = Sat Mar 31 2018 18:43:15 GMT+0800 (CST)
CL
#putput>>>>>>>
执行shell
命令方便多了,不再用Runtime.getRuntime().exec("hostname")
,速度还邦邦快,可以的。
[–/--]176 Mechanical Checking of Caller-Sensitive Methods
Improve the security of the JDK’s method-handle implementation by replacing the existing hand-maintained list of caller-sensitive methods with a mechanism that accurately identifies such methods and allows their callers to be discovered reliably.
[–/--]179 Document JDK API Support and Stability
There is a long-standing shortcoming in the JDK in terms of clearly specifying the support and stability usage contract for com.sun.* types and other types shipped with the JDK that are outside of the Java SE specification. These contracts and potential evolution policies should be clearly captured both in the source code of the types and in the resulting class files. This information can be modeled with JDK-specific annotation types.
[vm/–]142 Reduce Cache Contention on Specified Fields
Define a way to specify that one or more fields in an object are likely to be highly contended across processor cores so that the VM can arrange for them not to share cache lines with other fields, or other objects, that are likely to be independently accessed.
好像是针对多核内存竞争的优化。
[vm/gc]122 Remove the Permanent Generation
Remove the permanent generation from the Hotspot JVM and thus the need to tune the size of the permanent generation.
Java8 JVM
移除了永久代,再也看不到java.lang.OutOfMemory: PermGen space
的异常了,移除工作在Java7
就开始了,把一些原本放在永久带的转移到了Java Heap
或Native Heap
中,譬如符号引用(Symbols)
转移到了native heap
;字面量(interned strings)
转移到了java heap
;类的静态变量(class statics)
转移到了java heap
,相当于在Java7
做了一次deprecate
。
替代永久代的是元空间Metaspace
,不过Metaspace
是放在本地内存当中的,空间大小取决于本地内存,一定程度上避免了内存溢出。
更多相关解释:JDK8中的永久代
[vm/gc]173 Retire Some Rarely-Used GC Combinations
Remove three rarely-used combinations of garbage collectors in order to reduce ongoing development, maintenance, and testing costs.
移除了三种收集器组合,DefNew + CMS
ParNew + SerialOld
Incremental CMS
。
更多收集器问题:GC算法 垃圾收集器
[vm/rt]136 Enhanced Verification Errors
Provide additional contextual information about bytecode-verification errors to ease diagnosis of bytecode or stackmap deficiencies in the field.
[vm/rt]147 Reduce Class Metadata Footprint
Reduce HotSpot’s class metadata memory footprint in order to improve performance on small devices.
[vm/rt]148 Small VM
Support the creation of a small VM that is no larger than 3MB.
[vm/rt]171 Fence Intrinsics
Add three memory-ordering intrinsics to the sun.misc.Unsafe class.
Unsafe
是一个神奇的类,如果哪天想要绕开JVM
干一些事情,可以考虑看看Unsafe
的代码找些灵感,特别是可以用来调试和学习。
Unsafe
类介绍Java魔法类:sun.misc.Unsafe
[core/–]153 Launch JavaFX Applications
Enhance the java command-line launcher to launch JavaFX applications.
[core/lang]101 Generalized Target-Type Inference
Smoothly expand the scope of method type-inference to support (i) inference in method context and (ii) inference in chained calls.
这个特性主要是加强了泛型的类型推断。我们先用Java8
写一段代码:
public class TargetType {
public static void main(String[] args){
MyList<String> myList = MyList.nil();
MyList<String> myList1 = MyList.cons("head",MyList.nil());//①
String head = MyList.nil().head();//②
}
static class MyList<T> {
static <Z> MyList<Z> nil() {
return null;
}
static <Z> MyList<Z> cons(Z head, MyList<Z> tail) {
return null;
}
T head() {
return null;
}
}
}
上面这段代码在编译时不会出任何错误,①和②没有任何错误,但是在Java7
中就会出错,因为两处变量都声明泛型为String
类型,但是赋值的时候没有显示的表名MyList
中的泛型到底是什么类型,于是使用Object
,编译会提示错误:Required:java.lang.String Found:java.lang.Object
;②也是同样的问题。因为Java7
只允许引用确定的泛型,这两个地方的引用都是模糊不清的,Java7
中只能这么写:
MyList<String> myList = MyList.nil();
MyList<String> myList1 = MyList.cons("head",MyList.<String>nil());
String head = MyList.<String>nil().head();
Java8
加强了类型推断,参数引用和方法链调用的泛型不再需要明确指定,完全跟需要返回的类型一致。
[core/lang]104 Annotations on Java Types
这里主要有两个改动,一个是类型注解,一个是重复注解。前者扩展了注解可以添加的位置,增加了两种位置的注解类型TYPE_PARAMETER
和TYPE_USE
,TYPE_PARAMETER
表示该注解可以用在泛型的类型生命处,TYPE_USE
表示注解可以使用在任何类型前面,比如:
@Target(ElementType.TYPE_USE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Annotation1 {
String value();
}
@Target(ElementType.TYPE_PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface Annotation2{
String value();
}
@Annotation1("type")
public class TestA<@Annotation2("type parameter statement") T> implements A<T> {
@Annotation1("field")
public String field;
@Annotation1("method")
@Override
public String test(@Annotation1("parameter") T s) throws @Annotation1("throw exception") Exception {
Date date = new @Annotation1("statement") Date();
String ss = (@Annotation1("cast") String)s;
return s.toString() + date.toString();
}
public String getField() {
return field;
}
}
类型注解被用来支持在Java
的程序中做强类型检查。配合第三方插件工具Checker Framework
,可以在编译的时候检测出runtime error(eg:UnsupportedOperationException
; NumberFormatException
;NullPointerException
异常等都是runtime error),以提高代码质量,这就是类型注解的作用。
至于重复注解,Java8以前,是不允许同一个注解在同一个地方使用多次,比如在同一类上多次使用同一注解,Java8可以重复使用注解。其实Java8以前也可实现一个位置使用多个相同的注解,比如定义一个元注解,再定义另一个新的注解,把元注解的数组对象作为域,就可以在这个新的注解中以数组的形式定义多个元注解,这种方式的可读性不高。Java8把这种显示的方式给隐藏了,实现原理和老办法是一样的,因此这只是一个编译层面的改动,不是语言层面的改动,从重复注解的定义和反射检索就可以看出:
public class RepeatAnnotation {
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(Roles.class)//元注解制定重复注解存放的容器,加上Repeatable注解可以实现重复注解而已
public @interface Role{
String value();
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Roles{
Role[] value();//容器里和老办法一样,是元注解的数组
}
@Role("dba")
@Role("sys")
public static class Test{
}
public static void main(String[] args){
for (Annotation annotation : new Test().getClass().getAnnotationsByType(Role.class)) {
System.out.println(annotation);
}
//@com.chenlei.test.RepeatAnnotation$Role(value=dba)
//@com.chenlei.test.RepeatAnnotation$Role(value=sys)
//通过具体类型可以获取多个相同类型的注解列表
for (Annotation annotation : new Test().getClass().getAnnotations()) {
System.out.println(annotation);
}
//@com.chenlei.test.RepeatAnnotation$Roles(value=[@com.chenlei.test.RepeatAnnotation$Role(value=dba), @com.chenlei.test.RepeatAnnotation$Role(value=sys)])
//如果不指定类型,其实任然是老版本的检索结果
}
}
[core/lang]105 DocTree API
Extend the Compiler Tree API to provide structured access to the content of javadoc comments.
针对javadoc
的一些扩展,可生成更强大的文档。
[core/lang]106 Add Javadoc to javax.tools
Extend the javax.tools API to provide access to javadoc.
为上一个改动而做的改动。
[core/lang]117 Remove the Annotation-Processing Tool (apt)
移除了APT,APT是一种处理注解的工具,确切的说它是javac
的一个工具,它用来在编译时扫描和处理注解,通过注解信息生成一些附属文件(比如源文件,类文件,程序发布描述文件等),这些附属文件的内容也都是与源代码相关的,换句话说,使用APT可以代替传统的对代码信息和附属文件的维护工作。比如Mybatis
的Mapper
类和mapping.xml
文件等。
Java7开始就增加了Pluggable Annotation Processing API支持,旨在替代APT,Java8中完全移除了APT,使用Pluggable Annotation Processing API可以在编译时修改语法树本身,再根据修改后的语法树编译,比如Lombok
就是根据这个来实现的,不过使用Pluggable Annotation Processing API的Processor
必须事先编译好或者放入编译好的jar
包,否则会报错。
[core/lang]118 Access to Parameter Names at Runtime
在jdk 1.8
之前,想要通过反射获得某一个方法的参数类型是轻而易举,但是想要获取这个参数的名称,必须借助第三方字节码处理工具,比如asm
、javassist
等,它们的原理是:java
字节码为每个方法保存了一份方法本地变量列表,可以使用字节码读取工具把这个方法的变量列表读出来。这在IDE提示非常有用,可能还有其它的特殊使用场景,具体使用方法:Java获取函数参数名称的几种方法。
但是这种方法太麻烦了,jdk 1.8
提供了原生的方法,可以直接通过反射获取参数名称:
public class TestGetParameterName {
public void test(String stringName, Integer integerName, List<String> stringListName){
System.out.println();
}
public static void main(String args[]) throws NoSuchMethodException {
Class clazz = new TestGetParameterName().getClass();
Method method = clazz.getDeclaredMethod("test", String.class, Integer.class, List.class);
Parameter[] parameters = method.getParameters();
for (Parameter parameter : parameters) {
System.out.println(parameter.getName());
}
}
}
/**
stringName
integerName
stringListName
*/
但是并不是直接这样写就完事儿了,因为实现这个功能的原理是:在class文件里,每个方法都加上了一个参数列表的元数据,只需要读取这个元数据就可以了,不过这里有个开关,而且默认是关闭的,需要在编译时加上-parameters
参数打开,才能在class文件里加上元数据;如果是maven,可以在pom文件机上:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<compilerArgument>-parameters</compilerArgument>
</configuration>
</plugin>
普通IDEA项目可以在这里编辑:
[core/lang]120 Repeating Annotations
104里面已经解释了,可以可以在相同位置写多个相同的注解。
[core/lang]139 Enhance javac to Improve Build Speed
- Increase build speed by having javac use all cores and reuse javac in a server process.
- Simplify work for developers by having javac build incrementally.
多核支持、重用javac进程,增量编译,提高编译速度。
[core/lang]172 DocLint
提供了检查javadoc
注释的方法,包括HTML标签、语法等,依赖于DocTree API
,可以在javac中使用-Xdoclint or -Xdoclint:args.
参数开启、关闭或其他操作,集成在IDE中检查是非常好的。
[core/libs]103 Parallel Array Sorting
在java.util.Arrays
类中添加了几个基于Fork/Join
框架的并行排序算法。
public class ArraysForkJoin {
public static void main(String[] args){
int[] array = new int[100000000];
Random random = new Random();
for (int i = 0; i < 100000000; i++) {
array[i] = random.nextInt();
}
long start = System.currentTimeMillis();
Arrays.sort(array);
long end = System.currentTimeMillis();
System.out.println("normal " + (end - start) + "ms");
start = System.currentTimeMillis();
Arrays.parallelSort(array);
end = System.currentTimeMillis();
System.out.println("parallel " + (end - start) + "ms");
}
}
/**
* normal 9605ms
* parallel 1082ms
*/
可以看出数据量很大的时候,并行还是快,但是数据量不大的时候差别很小,因为parallelSort()
方法的阈值是8192
,只有数组长度超过8192
才会使用Fork/Join
并行框架。
[core/libs]107 Bulk Data Operations for Collections
Collection提供了基于lambda表达式来批处理大数据的方法特性(filter/map/reduce for Java
),包括并行和线性,其中并行也是基于Fork/Join
方法来的。
[core/libs]109 Enhance Core Libraries with Lambda
Java core library APIs
中可以使用lambda表达式重写的,都提供了lambda表达式的实现,改进可用性和易用性。
[core/libs]112 Charset Implementation Improvements
优化了字符集处理性能。
Summary
Improve the maintainability and performance of the standard and extended charset implementations.
Motivation
- Decrease the size of installed charsets
- Reduce maintenance cost by generating charset implementations at build time from simple text-based mapping tables
- Improve the performance of encoding/decoding
[core/libs]119 javax.lang.model Implementation Backed by Core Reflection
Provide an implementation of the javax.lang.model.* API backed by core reflection rather than by javac. In other words, provide an alternate API to access and process the reflective information about loaded classes provided by core reflection.
不是很懂。
[core/libs]135 Base64 Encoding & Decoding
提供了Base64编码解码的标准API,有三类静态方法:Basic/MIME/URL
,8以前没有一套标准的Base64编码工具,jdk有几个实现,但是要么Deprecated要么性能不佳,现在的java.util.Base64
完全终结了这种混乱。
public class Base64Test {
public static void main(String[] args) throws UnsupportedEncodingException {
String plainText = "Java Base64 编码";
String encryptText = Base64.getEncoder().encodeToString(plainText.getBytes("UTF-8"));
System.out.println("Basic encrypt: " + encryptText);
System.out.println("Basic plain: " + new String(Base64.getDecoder().decode(encryptText), "UTF-8"));
String plainUrl = "https://www.baidu.com/s?ie=utf-8&f=3&rsv_bp=1&tn=06074089_58_pg&wd=Base64&oq=%25E5%258A%25A0%25E5%25AF%2586%2520%25E8%258B%25B1%25E6%2596%2587&rsv_pq=ed2c605300005e79&rsv_t=ca15TjNc0Y6Rbw3L283mux34a9iENuJUycgcvGf9g2DD1mrb4oCcozm5ue3vLHG6bzzMdYY&rqlang=cn&rsv_enter=0&inputT=221146&sug=%25E5%258A%25A0%25E5%25AF%2586%2520%25E8%258B%25B1%25E6%2596%2587&rsv_sug3=32&rsv_sug1=28&rsv_sug7=100&prefixsug=Base64&rsp=0&rsv_sug4=221146";
String encryptUrl = Base64.getUrlEncoder().encodeToString(plainUrl.getBytes());
System.out.println("Url encrypt: " + encryptUrl);
System.out.println("Url plain: " + new String(Base64.getUrlDecoder().decode(encryptUrl), "UTF-8"));
}
}
[core/lib]149 Reduce Core-Library Memory Usage
Reduce the dynamic memory used by core-library classes without adversely impacting performance.
[core/lib]150 Date & Time API
Define a new date, time, and calendar API for the Java SE platform
在1.8之前,使用java.util.Date
真的非常麻烦,非线程安全且性能堪忧,不稳定,我一般都用joda-time
代替,后者在日期处理上完胜java.util.Date
。
1.8提供了全新的日期类型:Instant
LocalDate
LocalTime
LocalDateTime
ZonedDateTime
。它们和String
一样,是不变的类型(final class
),是线程安全的。日期的比较、加减、解析、格式化等也非常方便,虽然不是特别熟悉,但是在某些无法使用joda-time
的情况下,可以考虑使用新的日期类型。
更多信息:
jdk1.8 date日期的处理(一)
jdk1.8 date日期的处理(二)
[core/libs]155 Concurrency Updates
并发的一些改进,很多并发类型和操作摒弃了纯synchronized
的实现,几乎都改成了synchronized
+ CAS(Compare and Swap)
来实现,这里又是一个超级大话题,以后单独总结并发。
- 增加
DoubleAccumulator
LongAccumulator
DoubleAdder
LongAdder
等类,相当于改进了AtomicLong
等类,在高并发下,前者效率更高,并发基于CAS
实现。 ConcurrentHashMap
依然使用数组+链表+红黑树实现,但保证线程安全不再使用Segment
加锁实现,而是使用synchronized
+CAS
实现。前者虽然不是对整个Map
加锁,保证对不在某个被锁定的Segment
内元素的访问不受影响,比HashTable
纯synchronized
的实现效率高一些,但是在数据量很大,频繁存储的情况下,比如作为缓存,性能并不太好,改用CAS
实现,元素的存储互不影响,适合用作频繁存储的情况下。- 提升
ForkJoinPools
性能。 - 增加了
StampedLock
CompletableFuture
等新的Lock
和Future
实现,前者支持乐观锁,后者能快速实现多个future之间的关联等。
[core/libs]170 JDBC 4.2
JDBC
的一些小幅改动,包括:
- 支持
LocalDate
等新的时间类型 CallableStatement
支持REF_CURSOR
- 指定
DataSource
所需属性 DatabaseMetaData.getIndexInfo
获取数据库元数据接口中的获取索引方法返回数据加了两列CARDINALITY
PAGES
DatabaseMeta
新增一个返回数据库LOB
对象的最大长度(This includes optional CLOB, Memo and Text fields)- 一些清理
[core/libs]177 Optimize java.text.DecimalFormat.format
优化了数字格式化,对于小数部分在2到3位的小数,先乘以100或1000,变成整数,处理完再变成小数,速度更快,并且可以避免double类型精度问题。
[core/libs]178 Statically-Linked JNI Libraries
Enhance the JNI specification to support statically linked native libraries.
[core/libs]180 Handle Frequent HashMap Collisions with Balanced Trees
java8以前的HashMap
和 LinkedHashMap
解决hash冲突只是简单地将所有Entry放在一个链表里,这就导致在冲突严重的情况下,在某一个bucket中查询一个key,最坏情况下时间复杂度是O(n),java8中当bucket中的元素个数超过了某个阈值时,会转换成一个平衡二叉树,最坏情况下查找的时间复杂度降到了O(logn)。
ConcurrentHashMap
和HashMap
类似,用的是红黑树,但是Hashtable
并没有使用平衡二叉树,依然保留原有的代码,因为一些遗留代码依赖于它的遍历顺序(哪里?并不知道),但是使用二叉树会导致遍历顺序不可控制;WeakHashMap
也没有改变,因为弱键的复杂性导致微基准测试性能下降到无法接受的地步;IdentityHashMap
也不需要改变,因为IdentityHashMap
是使用System.identityHashCode()
生成hash code,冲突通常情况下很少。
[core/i18n]127 Improve Locale Data Packaging and Adopt Unicode CLDR Data
The CLDR (Common Locale Data Repository) is a set of data collected by the Unicode Consortium that many libraries use to provide data related to internationalization.
跟国际化相关的东西吧,差点就触及到了知识盲区,不做深入了解。
[core/i18n]BCP 47 Locale Matching
Define APIs so that applications that use BCP 47 language tags (see RFC 5646) can match them to a user’s language preferences in a way that conforms to RFC 4647.
又是和CLDR
类似的。
[core/i18n]133 Unicode 6.2
Extend existing platform APIs to support version 6.2 of the Unicode Standard.
支持Unicode 6.2
。
[core/net]184 HTTP URL Permissions
Define a new type of network permission which grants access in terms of URLs rather than low-level IP addresses.
java8之前有java.net.SocketPermission
类管理网络连接权限,但是这个类有以下两个缺点:
- 基于最基础的
TCP
连接,因此无法区分TCP
连接和HTTP
连接,所以不能在针对同一台主机某些HTTP
连接被允许但某些TCP
连接不被允许的情况下使用; - 基于IP而不是主机名或域名,因此如果同一台主机上有两个
HTTP
server,是无法做出区分的,不适用同一主机上于允许一个服务禁止另一个服务的情况。
java8引入了一新的URLPermissions
,可以通过HTTP METHOD(GET POST DELETE etc.)
、URL正则、权重、路径等分配权限,最后依然是转换成SocketPermission
生效。具体以后会在IO/NETWORK总结(坑未填)。
[core/sec]113 MS-SFU Kerberos 5 Extensions
[core/sec]114 TLS Server Name Indication (SNI) Extension
[core/sec]115 AEAD CipherSuites
[core/sec]121 Stronger Algorithms for Password-Based Encryption
[core/sec]123 Configurable Secure Random-Number Generation
[core/sec]124 Enhance the Certificate Revocation-Checking API
[core/sec]129 NSA Suite B Cryptographic Algorithms
[core/sec]130 SHA-224 Message Digests
[core/sec]131 PKCS#11 Crypto Provider for 64-bit Windows
[core/sec]140 Limited doPrivileged
[core/sec]166 Overhaul JKS-JCEKS-PKCS12 Keystores
[web/jaxp]185 Restrict Fetching of External XML Resources
上面这些都是关于安全的,看不懂。