jdk11新特性,是否有必要从JDK8切换到JDK11

文章目录

          • 1.完全支持Linux容器(包括docker)
          • 2.ZGC
          • 3.全新的 HTTP 客户端 API
          • 4.模块化(Module)
          • 5.其他
          • 6.是否切换到JDK11

随着2022年jdk11的使用率首次超过jdk8,要开始关注jdk11的一些新特性,这里面最主要的,根据网上的资料,分为这几块。

1.完全支持Linux容器(包括docker)

许多运行在Java虚拟机中的应用程序(包括Apache Spark和Kafka等数据服务以及传统的企业应用程序)都可以在Docker容器中运行。
但是在Docker容器中运行Java应用程序一直存在一个问题,那就是在容器中运行JVM程序在设置内存大小和CPU使用率后,会导致应用程序的性能下降。
这是因为Java应用程序没有意识到它正在容器中运行。
随着Java 10的发布,这个问题总算得以解决,JVM现在可以识别由容器控制组(cgroups)设置的约束。
可以在容器中使用内存和CPU约束来直接管理Java应用程序,其中包括:

  • 遵守容器中设置的内存限制
  • 在容器中设置可用的CPU
  • 在容器中设置CPU约束

Java 10的这个改进在Docker for Mac、Docker for Windows以及Docker Enterprise Edition等环境均有效。

2.ZGC

GC是java主要优势之一。 然而, 当GC停顿太长, 就会开始影响应用的响应时间。 消除或者减少GC停顿时长, java将对更广泛的应用场景是一个更有吸引力的平台。 此外, 现代系统中可用内存不断增长,用户和程序员希望JVM能够以高效的方式充分利用这些内存, 并且无需长时间的GC暂停时间。
ZGC, A Scalable LowLatency Garbage Collector(Experimental)ZGC, 这应该是JDK11最为瞩目的特性,没有之一。 但是后面带了Experimental,说明这还不建议用到生产环境。
ZGC 是一个并发, 基于region, 压缩型的垃圾收集器, 只有root扫描阶段会STW(stop the world), 因此GC停顿时间不会随着堆的增长和存活对象的增长而变长。

特点:

  • GC暂停时间不会超过10ms;
  • 既能处理几百兆的小堆, 也能处理几个T的大堆(OMG);
  • 和G1相比, 应用吞吐能力不会下降超过15%;
  • 为未来的GC功能和利用colord指针以及Load barriers优化奠定基础;
  • 初始只支持64位系统;

ZGC的设计目标是:
支持TB级内存容量, 暂停时间低(<10ms) , 对整个程序吞吐量的影响小于15%。 将来还可以扩展实现机制, 以支持不少令人兴奋的功能, 例如多层堆(即热对象置于DRAM和冷对象置于NVMe闪存) ,或压缩堆。

JDK11生产服务器有博主进行了测试:总体来说还处在实验阶段。

https://www.jianshu.com/p/78fcab6c318c

3.全新的 HTTP 客户端 API

HTTP,用于传输网页的协议,早在1997年就被采用在目前的1.1版本中。直到2015年, HTTP2才成为标准。

jdk11新特性,是否有必要从JDK8切换到JDK11_第1张图片

  • HTTP/1.1和HTTP/2的主要区别是如何在客户端和服务器之间构建和传输数据。
  • HTTP/1.1依赖于请求/响应周期。 HTTP/2允许服务器“push”数据:它可以发 送比客户端请求更多的数据。这使得它可以优先处理并发送对于首先加载网 页至关重要的数据。
  • 这是 Java 9 开始引入的一个处理 HTTP 请求的的 HTTP Client API, 该API 支持同步和异步, 而在 Java11 中已经为正式可用状态, 你可以在java.net 包中找到这个 API。它 将 替 代 仅 适 用 于 blocking 模 式 的 HttpURLConnection( HttpURLConnection是在HTTP 1.0的时代创建的, 并使用了协议无关的方 法) , 并提供对WebSocket 和 HTTP/2的支持。
  HttpClient client = HttpClient.newHttpClient();
  HttpRequest request =
  HttpRequest.newBuilder(URI.create("http://127.0.0.1:8080/test/")).build();
  BodyHandler responseBodyHandler = BodyHandlers.ofString();
  // 同步
  HttpResponse response = client.send(request, responseBodyHandler);
  String body = response.body();
  System.out.println(body);
   // 异步
 CompletableFuture> sendAsync = client.sendAsync(request, HttpResponse.BodyHandlers.ofString());
 //这里会阻塞
 HttpResponse response1 = sendAsync.get();
 System.out.println(response1.body());
  

// 以下是结合异步优化的写法
 HttpClient client = HttpClient.newHttpClient();
 HttpRequest request =
 HttpRequest.newBuilder(URI.create("http://127.0.0.1:8080/test/")).build();
 BodyHandler responseBodyHandler = BodyHandlers.ofString();
 //这里使用JDK8的CompletableFuture 进行了异步编程 
 CompletableFuture> sendAsync =thenAccept 
 client.sendAsync(request, responseBodyHandler);
 sendAsync.thenApply(t -> t.body()).thenAccept(System.out::println);
 HttpResponse response = sendAsync.get();
 String body = response.body();
 System.out.println(body);
4.模块化(Module)

1.什么是模块化?

模块化就是增加了更高级别的聚合,是Package的封装体。Package是一些类路径名字的约定,而模块是一个或多个Package组成的封装体。

java9以前 :package => class/interface。

java9以后 :module => package => class/interface。

那么JDK被拆为了哪些模块呢?打开终端执行java --list-modules查看。

lixiaoshuang@localhost  ~ java --list-modules
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]

2.为什么这么做?

大家都知道JRE中有一个超级大的rt.jar(60多M),tools.jar也有几十兆,以前运行一个hello world也需要上百兆的环境。

  • 让Java SE程序更加容易轻量级部署。
  • 强大的封装能力。
  • 改进组件间的依赖管理,引入比jar粒度更大的Module。
  • 改进性能和安全性。

3.怎么定义模块?

模块的是通过module-info.java进行定义,编译后打包后,就成为一个模块的实体。下面来看下最简单的模块定义。

jdk11新特性,是否有必要从JDK8切换到JDK11_第2张图片

jdk11新特性,是否有必要从JDK8切换到JDK11_第3张图片

4.模块的关键字

· open

用来指定开放模块,开放模块的所有包都是公开的,public的可以直接引用使用,其他类型可以通过反射得到。

open module module.one {
 //导入日志包
 requires java.logging;
}

· opens

opens 用来指定开放的包,其中public类型是可以直接访问的,其他类型可以通过反射得到。

module module.one {
 opens ;
}

· exports

exports用于指定模块下的哪些包可以被其他模块访问。

module module.one {
 
 exports ;
 
 exports  to , ...;
}

· requires

该关键字声明当前模块与另一个模块的依赖关系。

module module.one {
 requires ;
}

· uses、provides…with…

uses语句使用服务接口的名字,当前模块就会发现它,使用java.util.ServiceLoader类进行加载,必须是本模块中的,不能是其他模块中的.其实现类可以由其他模块提供。

module module.one {
 //对外提供的接口服务 ,下面指定的接口以及提供服务的impl,如果有多个实现类,用用逗号隔开
 uses <接口名>;
 provides <接口名> with <接口实现类>,<接口实现类>;
}
5.其他

包含STRING的增加apiStream的增强处理var关键字Jshell直接编译等,我觉得这些都不是很重要,属于锦上添花的功能需,要进行了解的话可以参考以下博主的详情描述。

感谢以下博主,部分引用自以下博主。

https://zhuanlan.zhihu.com/p/94459000

https://www.cnblogs.com/niujifei/p/15079097.html

6.是否切换到JDK11
  1. G1 GC平均速度通过Java 8切换到 Java 11 就有 16% 的改进,但是大部分项目都用不到,一些高实时性的游戏可以用;
  2. .Java 11支持源文件直接运行;
  3. 已完成项目不建议升级jdk11,或者新项目需要依赖现有代码,不建议升级jdk11,因为升级版本涉及到大量的旧代码移植,代码重写,架构重构,全量测试;
  4. 如果jdk8满足开发需求,并且需依赖现有以JDK8开发的代码,建议还是以jdk8进行开发,否则如果选用jdk11可能面临旧代码重写,架构重构,以及一些不知道的隐形依赖;
  5. 系统追求的是稳定并非技术,jdk8已被广泛验证非常稳定,而且目前主流开发版本确实也是8,技术还是要服务于业务,稳定大于一切;
  6. 从jdk8往上升级会出现一些jar依赖的改变,模块化带来的反射问题,classload的变化导致某些问题;
  7. Spring,Spring Boot,Spring Cloud,Dubbo,Guava,Jackson,Tomcat,JUnit等等项目都适配了JDK11,并且经历了生产环境的检验,才可以考虑是否将JDK8换成JDK11;

你可能感兴趣的:(docker,java,容器)