许多运行在Java虚拟机中的应用程序(包括Apache Spark和Kafka等数据服务以及传统的企业应用程序)都可以在Docker容器中运行。
但是在Docker容器中运行Java应用程序一直存在一个问题,那就是在容器中运行JVM程序在设置内存大小和CPU使用率后,会导致应用程序的性能下降。
这是因为Java应用程序没有意识到它正在容器中运行。
随着Java 10的发布,这个问题总算得以解决,JVM现在可以识别由容器控制组(cgroups)设置的约束。
可以在容器中使用内存和CPU约束来直接管理Java应用程序,其中包括:
Java 10的这个改进在Docker for Mac、Docker for Windows以及Docker Enterprise Edition等环境均有效。
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停顿时间不会随着堆的增长和存活对象的增长而变长。
特点:
ZGC的设计目标是:
支持TB级内存容量, 暂停时间低(<10ms) , 对整个程序吞吐量的影响小于15%。 将来还可以扩展实现机制, 以支持不少令人兴奋的功能, 例如多层堆(即热对象置于DRAM和冷对象置于NVMe闪存) ,或压缩堆。
JDK11生产服务器有博主进行了测试:总体来说还处在实验阶段。
https://www.jianshu.com/p/78fcab6c318c
HTTP,用于传输网页的协议,早在1997年就被采用在目前的1.1版本中。直到2015年, HTTP2才成为标准。
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);
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也需要上百兆的环境。
3.怎么定义模块?
模块的是通过module-info.java进行定义,编译后打包后,就成为一个模块的实体。下面来看下最简单的模块定义。
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 <接口实现类>,<接口实现类>;
}
包含STRING的增加api、Stream的增强处理、var关键字、Jshell直接编译等,我觉得这些都不是很重要,属于锦上添花的功能需,要进行了解的话可以参考以下博主的详情描述。
感谢以下博主,部分引用自以下博主。
https://zhuanlan.zhihu.com/p/94459000
https://www.cnblogs.com/niujifei/p/15079097.html