【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 {@Overridepublic void a() {System.out.println("A.a()");}}static class B implements If {@Overridepublic void a() {System.out.println("B.a()");}@Overridepublic void b() {System.out.println("B.b()");}}
}

这让虚拟扩展方法和abstract class有点相似,似乎两者变得更加模糊了。其实不然,接口依然代表like-a,抽象类依然代表is-a,接口依然不能写构造方法,接口还是不能有自己的属性,接口还是不能有finalprivate方法声明等等,在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

通常情况是:

  1. 先正常开发,或者先规定一个profile,比如compact1,只能使用这个profile下的包;
  2. 使用jdeps工具检查用到了哪个级别的profile,如果不能超出规定的profile,那就得改代码;
  3. 使用jrecreate创建空间占用更小的jre,注意jrecreate工具只在ORACLE JAVA SE EMBEDDED里才有的;
  4. 使用精简过后jre运行jar

下面是一个例子。

首先写好一个java hello world:

public static void main(String[] args){System.out.println("Hello World!");
}

然后打包成hello_world.jarIDEA·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/compact1Jretarget: linux_i586vm: minimalruntime: compact1 profiledebug: falsekeep-debug-info: falseno-compression: falsedry-run: falseverbose: falseextension: []
}
#output>>>>>>>>>>>

更多参数:Create Your JRE with jrecreate

最后的jre居然只有11M,将jrejar包考到目标设备,文件结构如下:

jar|_hello_world.jar
jre|-bin|-lib|_...# 试试执行
jre/bin/java -jar jar/hello_world.jar
#output>>>>>>>>>
Hello World!
#output>>>>>>>>>

这在嵌入式系统或者小设备上很有用,一个简单的程序不需要把100+Mjre打包过去,还是非常有用的。

[–/--]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
*/

还有一个很棒的特点是脚本支持heredocsshell 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 HeapNative 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_PARAMETERTYPE_USETYPE_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")@Overridepublic 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:UnsupportedOperationExceptionNumberFormatExceptionNullPointerException异常等都是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可以代替传统的对代码信息和附属文件的维护工作。比如MybatisMapper类和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之前,想要通过反射获得某一个方法的参数类型是轻而易举,但是想要获取这个参数的名称,必须借助第三方字节码处理工具,比如asmjavassist等,它们的原理是: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

  1. Increase build speed by having javac use all cores and reuse javac in a server process.
  2. 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内元素的访问不受影响,比HashTablesynchronized的实现效率高一些,但是在数据量很大,频繁存储的情况下,比如作为缓存,性能并不太好,改用CAS实现,元素的存储互不影响,适合用作频繁存储的情况下。
  • 提升ForkJoinPools性能。
  • 增加了StampedLock CompletableFuture等新的LockFuture实现,前者支持乐观锁,后者能快速实现多个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以前的HashMapLinkedHashMap解决hash冲突只是简单地将所有Entry放在一个链表里,这就导致在冲突严重的情况下,在某一个bucket中查询一个key,最坏情况下时间复杂度是O(n),java8中当bucket中的元素个数超过了某个阈值时,会转换成一个平衡二叉树,最坏情况下查找的时间复杂度降到了O(logn)。

ConcurrentHashMapHashMap类似,用的是红黑树,但是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类管理网络连接权限,但是这个类有以下两个缺点:

  1. 基于最基础的TCP连接,因此无法区分TCP连接和HTTP连接,所以不能在针对同一台主机某些HTTP连接被允许但某些TCP连接不被允许的情况下使用;
  2. 基于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

上面这些都是关于安全的,看不懂。

【JAVA拾遗】Java8新特性合辑相关推荐

  1. 【小家java】java8新特性之---全新的日期、时间API(JSR 310规范),附SpringMVC、Mybatis中使用JSR310的正确姿势

    [小家java]java5新特性(简述十大新特性) 重要一跃 [小家java]java6新特性(简述十大新特性) 鸡肋升级 [小家java]java7新特性(简述八大新特性) 不温不火 [小家java ...

  2. 【小家java】java8新特性之---Optional的使用,避免空指针,代替三目运算符

    相关阅读 [小家java]java5新特性(简述十大新特性) 重要一跃 [小家java]java6新特性(简述十大新特性) 鸡肋升级 [小家java]java7新特性(简述八大新特性) 不温不火 [小 ...

  3. java:java8新特性(Lambda 表达式、方法引用、构造器引用、数组引用、Stream API)

    速度更快 对 HashMap .ConcurrentHashMap低层的数据结构(数组+链表+二叉树) 低层的内存结构(将永久区更新为元空间,元空间使用的是物理内存) 代码更少(增加了新的语法 Lam ...

  4. 【Java】Java8新特性Lambda表达式和Stream API

    Lambda表达式是实现支持函数式编程技术的基础. 函数式编程与面向对象编程:函数式编程将程序代码看作数学中的函数,函数本身作为另一个函数参数或返回值,即高阶函数.而面向对象编程按照真实世界客观事物的 ...

  5. 【小家java】java9新特性(简述十大新特性) 褒贬不一

    相关阅读 [小家java]java5新特性(简述十大新特性) 重要一跃 [小家java]java6新特性(简述十大新特性) 鸡肋升级 [小家java]java7新特性(简述八大新特性) 不温不火 [小 ...

  6. 【小家java】java10新特性(简述十大新特性) 小步迭代

    相关阅读 [小家java]java5新特性(简述十大新特性) 重要一跃 [小家java]java6新特性(简述十大新特性) 鸡肋升级 [小家java]java7新特性(简述八大新特性) 不温不火 [小 ...

  7. Java基础20:Java8新特性终极指南

    更多内容请关注微信公众号[Java技术江湖] 这是一位阿里 Java 工程师的技术小站,作者黄小斜,专注 Java 相关技术:SSM.SpringBoot.MySQL.分布式.中间件.集群.Linux ...

  8. java stream byte_乐字节-Java8新特性之Stream流(上)

    上一篇文章,小乐给大家介绍了<Java8新特性之方法引用>,下面接下来小乐将会给大家介绍Java8新特性之Stream,称之为流,本篇文章为上半部分. 1.什么是流? Java Se中对于 ...

  9. 【JAVA基础】java基础之-java8新特性

    写在前面的话 脑子是个好东西,可惜的是一直没有搞懂脑子的内存删除机制是什么,所以啊,入行多年,零零散散的文章看了无数,却总是学习了很多也忘了很多. 痛定思痛的我决定从今天开始系统的梳理下知识架构,记录 ...

最新文章

  1. 遏制企业数据泄露之殇,大咖切磋云安全的攻防之道
  2. 3D视觉创新应用(三维重建)竞赛作品系列——人体三维精准量测与动作捕捉
  3. 如何构建识别图像中字符的自动程序?一文解读OCR与HTR
  4. spark算子大全glom_2小时入门Spark之RDD编程
  5. SpringBoot 配置错误页
  6. 【空间数据库技术】ArcSDE 10.1安装配置与企业级地理空间数据库的建立及连接
  7. 过年了,就别再背电脑回家。
  8. UVA11554 Hapless Hedonism【数学计算+大数】
  9. FPGA深度学习加速(1) - Xilinx ug892-Vivado design flows overview (Vivado设计流程简述) - 阅读笔记
  10. 发票OCR识别验真接口简介
  11. Ant Design of Vue去掉加载遮罩
  12. 解决:log4j警告:WARN Please initialize the log4j system properly
  13. spring aop统一进行日常及异常的处理
  14. 公有云 私有云及架构
  15. mysql 基本配置
  16. “羊了个羊”是如何吸引住你的
  17. Android视频直播的实现(推流完整实现001)
  18. c语言程序设计教程博客,嵌入式C语言教程以及C编程要素
  19. DVWA1.9之文件上传漏洞High级多种方法
  20. OpenGL超级宝典 统一变量(uniform variable)

热门文章

  1. 简述文件服务器的主要功能,文件服务器的作用
  2. FCFS算法java实现
  3. 极米年营收40亿同比增43%:CFO离职 遭百度减持套现3亿
  4. GRAINS: Generative Recursive Autoencoders for INdoor Scenes 2019 TOG(家居布局、树结构网络、RvNN)
  5. 静态分析网易新闻搜索加密参数sign
  6. python拍七游戏代码_python实现逢七拍腿小游戏的思路详解
  7. android虚拟内置sd卡,Android: 浅论虚拟SD卡的实现
  8. vue nodejs 构建_如何使用nodejs后端打字稿版本开发和构建vue js应用
  9. 坑之四 千年 (上)
  10. 【ESP32】ESP-Face 人脸检测识别