jdk11新特性研究

1、基于嵌套的访问控制

public class NestAccessExample {

public static class X {
    void test() throws Exception {
        Y y = new Y();
        y.y = 1;
        //jdk8会报IllegalAccessException,除非加field.setAccessible(true);
        //jdk11是反射和源码级权限一致,可以访问私有属性
        Field field = Y.class.getDeclaredField("y");
        field.setInt(y, 2);
    }
}

private static class Y {
    private int y;
}

public static void main(String[] args) throws Exception {
    new X().test();
}

}

2、JEP 309: Dynamic Class-File Constants(动态类文件常量)
动态语言Api测试,类型检查在动态过程中进行,Java的类型文件格式将被拓展,支持一种新的常量池格式:CONSTANT_Dynamic,加载CONSTANT_Dynamic会将创建委托给bootstrap方法。
public class DynamicTest {

public static void main(String[] args) throws Throwable {
    MethodHandles.Lookup lookup = MethodHandles.lookup();
    //动态查找类的方法,及返回信息
    MethodHandle mh = lookup.findStatic(DynamicTest.class, "test", MethodType.methodType(void.class));
    //执行方法
    mh.invokeExact();
}

private static void test() {
    System.out.println("test");
}

}

3、改进64函数, 提升64位机器下的运算性能
public class Aarch64Example {

public static void MathOnJdk11() {
    long startTime = System.nanoTime();
    for (int i = 0; i < 10000000; ++i) {
        Math.sin(i);
        Math.cos(i);
        Math.log(i);
    }
    long endTime = System.nanoTime();
    //jdk11:1353ms
    //jdk8:13099ms
    System.out.println(TimeUnit.NANOSECONDS.toMillis(endTime - startTime) + "ms");
}

public static void main(String[] args) {
    MathOnJdk11();
}

}

4、JEP 323: Local-Variable Syntax for Lambda Parameters(用于 Lambda 参数的局部变量语法)
Lambda参数的本地变量语法,允许var在声明隐式类型的lambda表达式的形参时使用,将隐式类型的lambda表达式中的形参声明的语法与局部变量声明的语法对齐
public class LocalVarExample {

private static void lambdaInJava8() {
    //参数列表,->,函数体
    new Thread(new Runnable() {
        @Override
        public void run() {
            System.out.println("before Java8");
        }
    }).start();

    new Thread(() -> System.out.println("in java8")).start();

    List<String> list = Arrays.asList("java8", "jdk8", "1.8");
    list.forEach(w -> {
        System.out.println("lambda in java8");
        System.out.println(w);
    });
}

//java10新特性:局部变量类型推断
private static void varInJava10() {
    //var是保留类型,不是关键字
    int var = 10;
    var i = 10;  //int 类型
    var str = "java10";
    var list1 = new ArrayList<String>();
    var map = Map.of(1, "a", 2, "b");
    for (var entry : map.entrySet()) {
        System.out.println(entry);
    }
}

// class ErrorUseVar {
// var i = 10; //不是局部变量,不允许
//
// var f(var str) { //不能用于函数参数
// return 10;
// }
// }

//使用var标识变量
private static void lambdaWithVarInJava11() {
    List<Integer> nums = Arrays.asList(7, 8, 9);
    nums.sort((Integer s1, Integer s2) -> {
        if (s1.equals(s2)) return 0;
        else return s1 > s2 ? 1 : -1;
    });
    nums.sort((var s1, var s2) -> {
        if (s1.equals(s2)) return 0;
        else return s1 > s2 ? 1 : -1;
    });
    System.out.println(nums);
    //(var x,y)->x.pro(y),要么同时隐式,要么同时显示声明
}

public static void main(String[] args) {
    //lambdaInJava8();
    varInJava10();
    lambdaWithVarInJava11();
}

}

5、JEP 321: HTTP Client (Standard)(标准HTTP客户端)

将JDK9引进并孵化的HTTP客户端API作为标准,即HTTP/2 Client。它定义了一个全新的实现了HTTP/2和WebSocket的HTTP客户端API,并且可以取代HttpURLConnection。
动机
已经存在的HttpURLConnection有如下问题:
在设计时考虑了多种协议,但是现在几乎所有协议现已不存在。
API早于HTTP/1.1并且太抽象;
使用很不友好;
只能以阻塞模式工作;
非常难维护;
public class HTTPClientExample {

//同步方法
private static void syncGet(String uri) throws Exception {
    HttpClient client = HttpClient.newHttpClient();
    HttpRequest request = HttpRequest.newBuilder().uri(URI.create(uri)).build();
    HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
    System.out.println(response.statusCode());
    System.out.println(response.body());
}

//异步方法,join是等待返回信息
private static void asyncGet(String uri) throws Exception {
    HttpClient client = HttpClient.newHttpClient();
    HttpRequest request = HttpRequest.newBuilder().uri(URI.create(uri)).build();
    CompletableFuture<HttpResponse<String>> future = client.sendAsync(request, HttpResponse.BodyHandlers.ofString());
    future.whenComplete((resp, ex) -> {
        if (ex != null) ex.printStackTrace();
        else {
            System.out.println(resp.statusCode());
            System.out.println(resp.body());
        }
    }).join();
}

public static void main(String[] args) throws Exception {
    String uri = "http://t.weather.sojson.com/api/weather/city/101030100";
    //syncGet(uri);
    asyncGet(uri);
}

}
6、JEP 327: Unicode 10

更新平台API支持Unicode 10.0版本(Unicode 10.0概述:Unicode 10.0 增加了8518 个字符, 总计达到了136,690个字符. 并且增加了4个脚本, 总结139个脚本, 同时还有56个新的emoji表情符号。参考:http://unicode.org/versions/Unicode10.0.0/)。
public class Unicode10Example {

public static void main(String[] args) {
    System.out.println("\uD83E\uDDDA");
    System.out.println("\uD83E\uDD92");
    System.out.println("\uD83E\uDD95");
}

}

7、启动单一文件的源代码程序
增强Java启动器支持运行单个Java源代码文件的程序。

单文件程序是指整个程序只有一个源码文件,通常是早期学习Java阶段,或者写一个小型工具类。以HelloWorld.java为例,运行它之前需要先编译。我们希望Java启动器能直接运行这个源码级的程序:
java HelloWorld.java

等价于:
javac -d HelloWorld.java
java -cp helloWorld
java Factorial.java 3 4 5
1
2
3
等价于:
javac -d Factorial.java
java -cp Factorial 3 4 5
到JDK10为止,Java启动器能以三种方式运行:

启动一个class文件;
启动一个JAR中的main方法类;
启动一个模块中的main方法类;
JDK11再加一个,即第四种方式:启动一个源文件申明的类。

8、可伸缩低延迟垃圾收集器
ZGC:这应该是JDK11最为瞩目的特性,没有之一。但是后面带了Experimental,说明还不建议用到生产环境。看看官方对这个特性的目标描述:

GC暂停时间不会超过10ms;
即能处理几百兆小堆,也能处理几个T的大堆(OMG);
和G1相比,应用吞吐能力不会下降超过15%;
为未来的GC功能和利用colord指针以及Load barriers优化奠定基础;
初始只支持64位系统
GC是Java主要优势之一。然而,当GC停顿太长,就会开始影响应用的响应时间。消除或者减少GC停顿时长,Java将对更广泛的应用场景是一个更有吸引力的平台。此外,现代系统中可用内存不断增长, 用户和程序员希望JVM能够以高效的方式充分利用这些内存,并且无需长时间的GC暂停时间。
ZGC一个并发,基于region,压缩型的垃圾收集器,只有root扫描阶段会STW,因此GC停顿时间不会随着堆的增长和存活对象的增长而变长。
ZGC和G1停顿时间比较:
ZGC
avg: 1.091ms (+/-0.215ms)
95th percentile: 1.380ms
99th percentile: 1.512ms
99.9th percentile: 1.663ms
99.99th percentile: 1.681ms
max: 1.681ms

G1
avg: 156.806ms (+/-71.126ms)
95th percentile: 316.672ms
99th percentile: 428.095ms
99.9th percentile: 543.846ms
99.99th percentile: 543.846ms
max: 543.846ms

用法:-XX:+UnlockExperimentalVMOptions -XX:+UseZGC
因为ZGC还处于实验阶段,所以需要通过JVM参数UnlockExperimentalVMOptions 来解锁这个特性。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
ZGC过程:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
9、新增的API方法
a、
String类中strip()方法:

 public String strip() {
        String ret = isLatin1() ? StringLatin1.strip(value)
                                : StringUTF16.strip(value);
        return ret == null ? this : ret;
    }

作用:删除前导和尾部的空格

isBlank()方法:

public boolean isBlank() {
        return indexOfNonWhitespace() == length();
    }

作用:判断字符串为空

lines()方法:

 public Stream<String> lines() {
        return isLatin1() ? StringLatin1.lines(value)
                          : StringUTF16.lines(value);
    }

作用:提取字符串中行的流,由行的终止符去分割

repeat(int count)方法:

public String repeat(int count) {
        if (count < 0) {
            throw new IllegalArgumentException("count is negative: " + count);
        }
        if (count == 1) {
            return this;
        }
        final int len = value.length;
        if (len == 0 || count == 0) {
            return "";
        }
        if (len == 1) {
            final byte[] single = new byte[count];
            Arrays.fill(single, value[0]);
            return new String(single, coder);
        }
        if (Integer.MAX_VALUE / count < len) {
            throw new OutOfMemoryError("Repeating " + len + " bytes String " + count +
                    " times will produce a String exceeding maximum size.");
        }
        final int limit = len * count;
        final byte[] multiple = new byte[limit];
        System.arraycopy(value, 0, multiple, 0, len);
        int copied = len;
        for (; copied < limit - copied; copied <<= 1) {
            System.arraycopy(multiple, 0, multiple, copied, copied);
        }
        System.arraycopy(multiple, 0, multiple, copied, limit - copied);
        return new String(multiple, coder);
    }

作用:返回字符串重复的次数

stripLeading()方法:

public String stripLeading() {
        String ret = isLatin1() ? StringLatin1.stripLeading(value)
                                : StringUTF16.stripLeading(value);
        return ret == null ? this : ret;
    }
作用:返回字符串并删除前导空格

stripTrailing()方法:

public String stripTrailing() {
        String ret = isLatin1() ? StringLatin1.stripTrailing(value)
                                : StringUTF16.stripTrailing(value);
        return ret == null ? this : ret;
    }
    作用:返回字符串并删除尾部空格

测试:

 public static void main(String[] args) {
        String example = " Hello,JDK11\u3000";
        String empty = "\u3000";
        System.out.println("原始字符串串:" + example);
        //对比trim和strip
        System.out.println("<trim->删除字符串头尾的空白符>:" + example.trim());//尾部多一个unicode空白符
        System.out.println("<strip->删除字符串头尾的空白符>:" + example.strip());//尾部没有unicode空白符
        System.out.println("<stringLeading->删除字符串头部的空白符>:" + example.stripLeading());
        System.out.println("<stringTrailing->删除字符串尾部的空白符>:" + example.stripTrailing());
        //对比isBlank和isEmpty
        System.out.println("<isBlank->是否为空或者仅包含空格>:" + empty.isBlank());//基于unicode去识别的
        System.out.println("<isEmpty->是否为空或者仅包含空格>:" + empty.isEmpty());
        //lines方法
        String lines = "Hello\nWorld\nJDK11";
        lines.lines().forEach(System.out::println);
        //repeat方法
        System.out.println("*".repeat(50));
    }

b、Files类
readString(Path path) 方法:

public static String readString(Path path) throws IOException {
        return readString(path, StandardCharsets.UTF_8);
    }
    作用:传递文件路径,返回文件内容的字符串

测试:

 public class FilesExample {

    public static void main(String[] args) throws Exception {
        String path = "jdk11_new_future.txt";
        Files.writeString(Path.of(path), "jdk11_new_future", StandardCharsets.UTF_8);
        System.out.println(Files.readString(Paths.get(path), StandardCharsets.UTF_8));
    }
}

c、List类
List.of()方法返回一个不可变对象

static <E> List<E> of(E e1, E e2, E e3) {
        return new ImmutableCollections.ListN<>(e1, e2, e3);
    }

测试:

public class ListExample {

    public static void main(String[] args) {
        List<String> list = List.of("java8", "java9", "java10");
        System.out.println(list);
        //list.clear();不可变对象不能修改
        //旧的方法:传入String[]
        String[] oldWay = list.toArray(new String[0]);
        //新的方式
        String[] newWay = list.toArray(String[]::new);
    }
}

10、jdk11其他新特性
在这里插入图片描述
a、JEP 318: Epsilon: A No-Op Garbage Collector(Epsilon — 一个无操作的垃圾收集器)
JDK上对这个特性的描述是:开发一个处理内存分配但不实现任何实际内存回收机制的GC,一旦可用堆内存用完,JVM就会退出。

如果有System.gc()的调用,实际上什么也不会发生(这种场景下和-XX:+DisableExplicitGC效果一样),因为没有内存回收,这个实现可能会警告用户尝试强制GC是徒劳。

用法非常简单:-XX:+UseEpsilonGC。

b、JEP 320: Remove the Java EE and CORBA Modules(删除 Java EE 和 CORBA 模块)
Java EE和CORBA两个模块在JDK9中已经标记"deprecated",在JDK11中正式移除。JDK中deprecated的意思是在不建议使用,在未来的release版本会被删除。
JavaEE由4部分组成:

JAX-WS (Java API for XML-Based Web Services),
JAXB (Java Architecture for XML Binding)
JAF (the JavaBeans Activation Framework)
Common Annotations.
但是这个特性和JavaSE关系不大。并且JavaEE被维护在GitHub (https://github.com/javaee) 中,版本同步造成维护困难。最后,JavaEE可以单独引用,maven中心仓库也提供了JavaEE (http://mvnrepository.com/artifact/javax/javaee-api/8.0) ,所以没必要把JavaEE包含到JavaSE中。

至于CORBA,使用Java中的CORBA开发程序没有太大的兴趣。因此,在JavaEE就把CORBA标记为"Proposed Optional",这就表明将来可能会放弃对这些技术的必要支持。

c、JEP 328: Flight Recorder(飞行记录器)
提供一个低开销的,为了排错Java应用问题,以及JVM问题的数据收集框架,希望达到的目标如下:

提供用于生产和消费数据作为事件的API;
提供缓存机制和二进制数据格式;
允许事件配置和事件过滤;
提供OS,JVM和JDK库的事件;
排错,监控,性能分析是整个开发生命周期必不可少的一部分,但是某些问题只会在大量真实数据压力下才会发生在生产环境。
Flight Recorder记录源自应用程序,JVM和OS的事件。 事件存储在一个文件中,该文件可以附加到错误报告中并由支持工程师进行检查,允许事后分析导致问题的时期内的问题。工具可以使用API从记录文件中提取信息。

d、JEP 329: ChaCha20 and Poly1305 Cryptographic Algorithms(ChaCha20 和 Poly1305 加密算法)
实现RFC 7539中指定的 ChaCha20 和 ChaCha20-Poly1305 两种加密算法。
唯一一个其他广泛采用的RC4长期以来一直被认为是不安全的,业界一致认为当下ChaCha20-Poly1305是安全的。

e、JEP 331: Low-Overhead Heap Profiling(低开销的 Heap Profiling)
提供一种低开销的Java堆分配采样方法,得到堆分配的Java对象信息,可通过JVMTI访问。希望达到的目标如下:

足够低的开销,可以默认且一直开启;
能通过定义好的程序接口访问;
能采样所有分配;
能给出生存和死亡的Java对象信息;
动机
对用户来说,了解它们堆里的内存是很重要的需求。目前有一些已经开发的工具,允许用户窥探它们的堆,比如:Java Flight Recorder, jmap, YourKit, 以及VisualVM tools.。但是这工具都有一个很大的缺点:无法得到对象的分配位置。headp dump以及heap histo都没有这个信息,但是这个信息对于调试内存问题至关重要。因为它能告诉开发者,他们的代码发生(尤其是坏的)分配的确切位置。

f、JEP 332: Transport Layer Security (TLS) 1.3(支持 TLS 1.3)
实现TLS协议1.3版本。(TLS允许客户端和服务端通过互联网以一种防止窃听,篡改以及消息伪造的方式进行通信)。
TLS 1.3是TLS协议的重大改进,与以前的版本相比,它提供了显着的安全性和性能改进。其他供应商的几个早期实现已经可用。我们需要支持TLS 1.3以保持竞争力并与最新标准保持同步。这个特性的实现动机和Unicode 10一样,也是紧跟历史潮流。

g、JEP 335: Deprecate the Nashorn JavaScript Engine(弃用 Nashorn JavaScript 引擎)
h、JEP 336: Deprecate the Pack200 Tools and API(弃用 Pack200 工具和 API)

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值