181: Nest-Based Access Control(基于嵌套的访问控制)
这个 JEP 最直接的表现就是修复了以下代码所表现出的问题:
import java.lang.reflect.Field;
/**
* JEP181 基于嵌套的访问控制
*/
public class JEP181 {
public static class Inner1 {
public void test() throws Exception {
Inner2 var2 = new Inner2();
var2.var2 = 1;
//此处在没有JEP181的版本中执行会抛出错误
final Field f2 = Inner2.class.getDeclaredField("var2");
f2.setInt(var2, 2);
}
}
public static class Inner2 {
private int var2;
}
public static void main(String[] args) throws Exception {
new Inner1().test();
}
}
异常栈信息:
Exception in thread "main" java.lang.IllegalAccessException: Class JEP181$Inner1 can not access a member of class JEP181$Inner2 with modifiers "private"
at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:102)
at java.lang.reflect.AccessibleObject.slowCheckMemberAccess(AccessibleObject.java:296)
at java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:288)
at java.lang.reflect.Field.setInt(Field.java:946)
at JEP181$Inner1.test(JEP181.java:18)
at JEP181.main(JEP181.java:30)
同时,查看内部类的字节码文件可以看到
左边的字节码的 10 行显示 Inner2 中存在一个 access$002(Inner2, I)I 的方法,这个方法正是对应了 Inner1.test 中的 var2.var2 = 1;
而右边字节码的第 10 行,则表明 Inner1 是直接操作的 Inner2 中的 var2 字段。
根据官方文档,认为 access$002 这种方法,打破了封装。这个方法具体是:
通过直接在该类中对传入的该类的对象进行赋值。
309:Dynamic Class-File Constants(动态的类文件常量)
在 Class-File 中添加了一个新的常量池形式,称之为 CONSTANT_Dynamic
常量池标记为 17(ASM 框架中 Symbol 类可以查看到该值)
根据文档描述,invokedynamic 指令已经难以完成当前对常量集编码的需要,所以引入了 CONSTANT_Dynamic,但目前为止该特性在 ASM API 中被注解为实验性接口。
* 由于目前该功能处于实验阶段,ASM并没有找到关于此功能实践代码,待补充315:改进 Aarch64 Intrinsics(改进 Aarch64 Intrinsics)
简单来说,在 AArch64 执行状态的 CPU 架构下,根据架构特性优化了多个 JAVA 方法。
例如 java.util.Math 下的
- sin (sine trigonometric function)
- cos (cosine trigonometric function)
- log (logarithm of a number)
提升了应用程序的基准测试性能。
318:Epsilon 垃圾回收器,又被称为"No-Op(无操作)"回收器
这是一个实验性质的 GC,简单来说,这个 GC 只会分配内存,而不会回收内存,当堆内存耗尽时,JVM 将直接关闭。
此 GC 因为不存在内存回收功能,所以编码者显式调用 System.gc();是不会进行任何操作的。
使用方法: 启动 JVM 时追加参数 -XX:+UseEpsilonGC
这个 GC 主要的目标:
- 性能测试:将此 GC 作为其他 GC 对比的标准。
- 内存压力测试:由于该 GC 不存在内存回收,所以不用像以前一样通过分析日志来判断应用程序运行时内存是否已经超过指定大小,通过指定该 GC 的内存大小(with -Xmx1g),可以断定再不存在内存回收的情况下,应用程序是否满足该条件。
- 虚拟机接口测试,主要用于虚拟机的垃圾收集器接口。
- 执行短暂时间的任务:这类任务通常通过退出来快速释放堆内存,所以没有必要在内存分配回收上消耗时间。
- 最后的延迟改进:利用此 GC 的特性有可能打造出一个不产生内存垃圾的应用程序。
- 最后的优化吞吐量。
320:移除 Java EE 和 CORBA 模块
移除 3 个特性:
- JAVAEE:该技术栈用于 java web 开发,主要由四种技术组成:JAX-WS(基于 XML 的 Web Service Api)、JAXB(用于 XML 和 JAVA 类的互相映射)、JAF(数据处理框架)、Common Annotations(通用注解,例如 @Resource 注解等),由于 EE 中出现了与 SE 开发无关的功能,且维护成本上升,在 JAVA SE 9 中被标记为弃用。
- CORBA:公共对象请求代理体系结构,一种规范。在 JAVA 中可以通过编写.idl 实现这个功能。由于该模块的编写复杂性及在现代应用程序中开发使用率不高且维护成本远超带来的益处,在 JAVA EE8 中被列为“Proposed Optional”, 在 JAVA SE 9 被标记为弃用。
- JTA(javax.transcation):该包为 CORBA 提供服务。
此 JEP 删除模块列表:
- java.xml.ws(JAX-WS)
- java.xml.bind(JAXB)
- java.activation(JAF)
- java.xml.ws.annotation(Common Annotations)
- java.corba(CORBA)
- java.transaction(JTA)
- java.se.ee(上面六个模块的聚合,JAVA SE 9 模块)
- jdk.xml.ws(JAX-WS 工具)
- jdk.xml.bind(JAXB 工具)
321:HTTP Client(Standard)
这是一个新的模块,包名称为java.net.http,而在 jdk8 中 HttpClient 位于sun.net.www.http.HttpClient;
此模块符合 Http 2.0 协议,且融入了 Reactive Flow 的概念。
关于响应式编程可以百度 Reactor 3 的文章看看。
323:用于 Lambda 参数的局部变量语法
JDK10 中已经具有自动类型推断功能了,就像如下
var list = new ArrayList();
但在 JDK10 运行一下代码会出现错误:
/**
* JEP323 用于 Lambda 参数的局部变量语法
* */
public class JEP323 {
public static void main( String[] args) {
Consumer<Integer> lambda = ( var a) -> {System.out.println(a);};
lambda.accept(3);
BinaryOperator<Integer> binaryOperator = (var a, var b) -> {return a + b;};
System.out.println(binaryOperator.apply(1, 2));
}
}
IDE 会提示:var 不该出现在此处。
但这段代码在 JDK11 的环境下能正常执行。
也就是以前的 var 只能用于局部变量和循环中,不能用于局部参数变量,此 JEP 已解决该问题。
但该局部参数变量 var 有个限制,不允许与隐式类型的参数混用,代码如下:
BinaryOperator<Integer> binaryOperator = (a, var b) -> {return a + b;};
System.out.println(binaryOperator.apply(1, 2));
lambda表达式中的(a, var b) a为隐式类型
324:采用 Curve25519 和 Curve448 算法实现的密钥协议
Curve25519:是目前最高水平的 Diffie-Hellman 函数,适用于广泛的场景,由 Daniel J. Bernstein 教授设计。由于 NIST P-256 的设计过程不透明,有来历不明的参数,被广泛怀疑有后门,所以设计了 Curve25519,Curve25519 的设计过程完全公开,没有任何来历不明的参数。
RFC 7748:定义了一种密钥协商方案,该方案比现有的椭圆曲线 Diffie-Hellman(ECDH)方案更有效和安全。
官方文档中示例 API 用法:
KeyPairGenerator kpg = KeyPairGenerator.getInstance("XDH");
NamedParameterSpec paramSpec = new NamedParameterSpec("X25519");
kpg.initialize(paramSpec);
// equivalent to kpg.initialize(255)
// alternatively: kpg = KeyPairGenerator.getInstance("X25519")
KeyPair kp = kpg.generateKeyPair();
KeyFactory kf = KeyFactory.getInstance("XDH");
BigInteger u = ...
XECPublicKeySpec pubSpec = new XECPublicKeySpec(paramSpec, u);
PublicKey pubKey = kf.generatePublic(pubSpec);
KeyAgreement ka = KeyAgreement.getInstance("XDH");
ka.init(kp.getPrivate());
ka.doPhase(pubKey, true);
byte[] secret = ka.generateSecret();
语法中出现的 alternatively: 只是标记作用,示意阅读者可以选XDH和X25519已定义的变量名前面加个 xxx: 对编译无影响,应该只是起说明作用, xxx不能使用关键字,且要符合JAVA变量命名的要求。
327:支持 Unicode 10 标准
支持 Unicode 10 标准,该标准具体内容可以查看 Unicode 10
主要影响的类:
- java.lang.String
- java.lang.Character
- java.awt.font.NumericShaper
- java.text.Bidi;
- java.text.BreakIterator;
- java.text.Normalizer;
328:飞行记录仪(JFR)
此 JEP 提供了低开销的数据收集框架,用于对 Java Application 和 HotSpot JVM 进行故障排查。
JFR 由以下部分组成:
- JFR 运行时引擎:控制缓存、IO 等、且提供了 C 和 JAVA 代码便携的动态连接库。
- JMC(Java Mission Control) 的 FR 插件,用于可视化界面。
使用该功能:
- 启动 JVM 时跟随参数:-XX:StartFlightRecording
- 也可以使用 bin / jcmd 工具启动:
$ jcmd JFR.start
$ jcmd JFR.dump filename=recording.jfr
$ jcmd JFR.stop
官方也为用户提供了自定义 JFR 事件: jdk.jfr.*
329:实现 ChaCha20 和 Poly1305 加密算法
此 JEP 实现了两种加密算法,且大家担心的 RC4 安全问题也可以使用较新的 ChaCha20 来替代。
330:直接启动单个 Java 源文件
此 JEP 在 java 启动器原来的启动模式基础上(启动类文件、启动 Jar 文件的主类、启动模块的主类)增加了一种新的启动方式:源文件模式
源文件模式有两种启动方式:
源码:
public class Hello{
public static void main(String[] args){
System.out.println("abc");
}
}
-
如果以上代码被命名为 Hello.java,则执行命令
java Hello.java
启动器会自动选择源文件模式。 -
如果该文件被命名为其他名字,例如 Hello123,则必须带有--source 参数:
java --source 11 Hello123
331:低开销的堆分配采样方法
略
332:支持 TLS 1.3
略
333:ZGC:可伸缩的低延迟垃圾回收器
这是一个可扩展的低延迟 GC。
特性:
- GC 暂停时间不应该超过 10ms。
- 处理的堆大小从百兆字节到兆兆字节
- 与使用 G1 的情况下,吞吐量减少不超过 15%
目前只支持 Linux/x64 平台。
335:弃用 Nashorn JavaScript 引擎
此引擎在 JDK8 中引入,因为 ECMAScript 语言快速迭代,Nashorn 维护成本上升,目前已标记为弃用,会在后续版本删除该引擎,但官网也明确表明,此引擎如果有可靠的开发人员进行维护,则撤销该决定。
336:弃用 Pack200 工具及其 API
Pack200 是 Jar 文件的压缩方案,是在由 JSR200 在 Java SE 5.0 引入的,而 JDK8 是该工具构建压缩时最后一个版本,从 JDK9 起已经不再依赖该工具。
删除原因:
- 由于当时的网络速率限制,需要 Pack200 来减少 Jar 文件的磁盘、带宽需求等。而现在资源有所提高,JDK 已经不需要 Pack200 了。
- 浏览器大多已不在运行 Applet 了
- 维护成本过高。
影响模块:
- java.util.jar.Pack200
- java.util.jar.Pack200.Packer
- java.util.jar.Pack200.Unpacker
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于