本文章属于Java 新特性教程 系列,已经收录在 Github.com/niumoo/JavaNotes ,点个赞,不迷路。

自从 Oracle 调整了 Java 的版本发布节奏之后,Java 版本发布越来越快,虽然都说 Java 版本任他发,我用 Java 8,不过新版本的 Java 功能还是要学习一下的。

Java 13 早在 2019 年 9 月就已经发布,虽然不是长久支持版本,但是也带来了不少新功能。

Java 13 官方下载:https://jdk.java.net/archive/

Java 13 官方文档:http://openjdk.java.net/projects/jdk/13/

Java 13 新功能

  1. JEP 350: 动态 CDS 存档
  2. JEP 351: ZGC,归还未使用的内存 (实验性)
  3. JEP 353: 重新实现 Socket API
  4. JEP 354: Switch 表达式 (二次预览)
  5. JEP 355: 文本块 (预览)

扩展:此文章属于Java 新特性教程 系列,会介绍 Java 每个版本的新功能,可以点击浏览。

1. JEP 350 动态 CDS 存档

JVM 启动时有一步是需要在内存中加载类,而如果有多个 jar,加载第一个 jar 的速度是最慢的。这就延长了程序的启动时间,为了减少这个时间,Java 10 引入了应用程序类数据共享(CDS)机制,它可以把你想共享的类共享在程序之间,使不同的 Java 进程之间共享这个类来减少这个类占用的空间以及加载速度。不过 Java 10 中使用这个功能的步骤比较繁琐。

扩展阅读:Java 10 新功能介绍

而 Java 13 中的 AppCDS,允许 Java 应用在程序执行结束时(如果 JVM 没有崩溃)进行动态存档;存储的内容包括所有加载的应用类型类和使用的类库,这些存储的类库本来并不存在于默认的 CDS 存档中。

使用这个功能非常简单,只需要在程序启动时增加启动参数 。

# ArchiveClassesAtExit,程序结束时动态存档
bin/java -XX:ArchiveClassesAtExit=hello.jsa -cp hello.jar Hello
# SharedArchiveFile,使用指定存档启动
bin/java -XX:SharedArchiveFile=hello.jsa -cp hello.jar Hello

2. JEP 351: ZGC,归还未使用的内存 (实验性)

在 Java 13 之前,ZGC 虽然在清理内存时导致的停顿时间非常少,但是即使内存已经长时间没有使用,ZGC 也不会将内存返还给操作系统,这对那些十分关注内存占用的应用程序非常不友好。

比如:

  • 资源按使用量付费的云上容器环境。

  • 应用虽然长时间闲置,但是占用了内存,导致运行的其他程序内存紧张。

而新增的这个功能,可以让 ZGC 归还长时间没有使用的内存给操作系统,这对某些用户来说十分友好。

3. JEP 353: 重新实现 Socket API

java.net.Socketjava.net.ServerSocket 类早在 Java 1.0 时就已经引入了,它们的实现的 Java 代码和 C 语言代码的混合,维护和调试都十分不易;而且这个实现还存在并发问题,有时候排查起来也很困难。

因此,在 Java 13 中引入了新的实现方式,使用了新的实现 NioSocketImpl 来代替老旧的 PlainSocketImpl 实现。虽然功能相同,但是老的方式在当前以及未来几个版本内不会删除,用户随时可以通过 -Djdk.net.usePlainSocketImpl 参数切换回老的实现方式,以兼容意外情况。

编写一个测试类可以发现这个变化。

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class Test {
public static void main(String[] args) {
try (ServerSocket serverSocket = new ServerSocket(8000)){
boolean running = true;
while(running){
Socket clientSocket = serverSocket.accept();
//do something with clientSocket
}
} catch (IOException e) {
e.printStackTrace();
}
}
}

使用 Java 13 运行,通过参数 -XX:+TraceClassLoading 追踪加载的类,日志中可以看到 NioSocketImpl

➜  develop ./jdk-13.0.2.jdk/Contents/Home/bin/java -XX:+TraceClassLoading Test.java | grep SocketImpl
[0.699s][info ][class,load] java.net.SocketImpl source: jrt:/java.base
[0.699s][info ][class,load] java.net.SocketImpl$$Lambda$173/0x0000000800c37440 source: java.net.SocketImpl
[0.702s][info ][class,load] sun.net.PlatformSocketImpl source: jrt:/java.base
[0.702s][info ][class,load] sun.nio.ch.NioSocketImpl source: jrt:/java.base
[0.713s][info ][class,load] sun.nio.ch.NioSocketImpl$FileDescriptorCloser source: jrt:/java.base

但在 Java 12 并不是 NioSocketImpl

➜  develop ./jdk-12.0.2.jdk/Contents/Home/bin/java -XX:+TraceClassLoading Test.java | grep SocketImpl
[0.665s][info ][class,load] java.net.SocketImpl source: jrt:/java.base
[0.665s][info ][class,load] java.net.AbstractPlainSocketImpl source: jrt:/java.base
[0.665s][info ][class,load] java.net.PlainSocketImpl source: jrt:/java.base
[0.665s][info ][class,load] java.net.SocksSocketImpl source: jrt:/java.base
[0.666s][info ][class,load] java.net.AbstractPlainSocketImpl$1 source: jrt:/java.base

4. JEP 354: Switch 表达式 (二次预览)

你为什么不愿意使用使用 switch 表达式?我想其中一个原因应该是, switch 表达式的代码不够美观优雅,甚至有些啰嗦。比如像下面的例子。

package com.wdbyte;

public class Java13Switch {
public static void main(String[] args) {
//通过传入月份,输出月份所属的季节
System.out.println(switchJava12Before("march"));
}
public static String switchJava12Before(String month) {
String reuslt = null;
switch (month) {
case "march":
case "april":
case "may":
reuslt = "春天";
break;
case "june":
case "july":
case "august":
reuslt = "夏天";
break;
case "september":
case "october":
case "november":
reuslt = "秋天";
break;
case "december":
case "january":
case "february":
reuslt = "冬天";
break;
}
return reuslt;
}
}

而在 Java 12 中,已经对 switch 进行了改进,使之可以使用 cast L -> 表达式进行操作,且可以具有返回值,这样代码就更加美观使用了,不过这在 Java 12 中是一个预览功能。

// 通过传入月份,输出月份所属的季节
public static String switchJava12(String month) {
return switch (month) {
case "march", "april", "may" -> "春天";
case "june", "july", "august" -> "夏天";
case "september", "october", "november" -> "秋天";
case "december", "january", "february" -> "冬天";
default -> "month erro";
};
}

扩展阅读:Java 12 新特性介绍JEP 325: Switch 表达式

而现在,在 Java 13 中,又对 switch 表达式进行了增强,增加了yield 关键词用于返回值,相比 break ,语义更加明确了。

public static String switchJava13(String month) {
return switch (month) {
case "march", "april", "may":
yield "春天";
case "june", "july", "august":
yield "夏天";
case "september", "october", "november":
yield "秋天";
case "december", "january", "february":
yield "冬天";
default:
yield "month error";
};
}

5. JEP 355: 文本块 (预览)

在这之前,如果我们把一个 JSON 赋值给字符串:

String content = "{\n"
+ " \"upperSummary\": null,\n"
+ " \"sensitiveTypeList\": null,\n"
+ " \"gmtModified\": \"2011-08-05 10:50:09\",\n"
+ " \"lowerGraph\": null,\n"
+ " \"signature\": \"\",\n"
+ " \"appName\": \"xxx\",\n"
+ " \"lowerSummary\": null,\n"
+ " \"gmtCreate\": \"2011-08-05 10:50:09\",\n"
+ " \"type\": \"CALL\",\n"
+ " \"name\": \"xxxx\",\n"
+ " \"subType\": \"yyy\",\n"
+ " \"id\": 1,\n"
+ " \"projectId\": 1,\n"
+ " \"status\": 1\n"
+ "}";

终于不用写丑陋的长字符串了,从 Java 13 开始你可以使用文本块的方式定义字符串了。

String content2 = """
{
"upperSummary": null,
"sensitiveTypeList": null,
"gmtModified": "2011-08-05 10:50:09",
"lowerGraph": null,
"signature": "",
"appName": "xxx",
"lowerSummary": null,
"gmtCreate": "2011-08-05 10:50:09",
"type": "CALL",
"name": "xxxx",
"subType": "yyy",
"id": 1,
"projectId": 1,
"status": 1
}
""";

不过这是一个预览功能,如果你要是在 Java 13 中使用需要手动开启预览功能,这个功能在 Java 15 中正式发布。

如果你想尝试,可以去下载最新版了,玩的开心。

参考

  1. http://openjdk.java.net/projects/jdk/13/
  2. https://nipafx.dev/java-application-class-data-sharing/
  3. https://www.wdbyte.com/2020/02/jdk/jdk12-feature/
  4. https://mkyong.com/java/what-is-new-in-java-13/
  5. Java 新特性教程

相关阅读

Hello world

我是程序猿阿朗,月朗风清的朗,一个每天搬砖的技术工具人。

如果想要订阅,可以关注公众号 “未读代码 ,或者未读代码博客,或者加我微信( wn8398)

本文也已经整理到 GitHub.com/niumoo/JavaNotes,欢迎 Star。

Java 17 将要发布,补一下 Java 13 中的新功能的更多相关文章

  1. Redis 6.0 正式版终于发布了!除了多线程还有什么新功能?

    Redis 6.0.1 于 2020 年 5 月 2 日正式发布了,如 Redis 作者 antirez 所说,这是迄今为止最"企业"化的版本,也是有史以来改动最大的一个 Redi ...

  2. Java Math 类中的新功能--浮点数

    Java™语言规范第 5 版向 java.lang.Math和 java.lang.StrictMath添加了 10 种新方法,Java 6 又添加了 10 种.这个共两部分的系列文章的 第 1 部分 ...

  3. java byte【】数组与文件读写(增加新功能)

    今天在测试直接写的文章: java byte[]数组与文件读写 时,想调用FileHelper类对字节数组以追加的方式写文件,结果无论怎样竟然数据录入不全,重新看了下文件的追加模式,提供了两种方式: ...

  4. 五指CMS发布1.4版本,更多的新功能

    五指cms v1.4变更: 新增内容手动分页新增百度地图新增订单管理模块新增订单地址管理增加Microsoft YaHei字体新增推广邀请模块新增私密下载,下载函数 新增百度地图新增筛选功能 修正全局 ...

  5. Java 17 新功能介绍(LTS)

    点赞再看,动力无限.Hello world : ) 微信搜「程序猿阿朗 」. 本文 Github.com/niumoo/JavaNotes 和 未读代码博客 已经收录,有很多知识点和系列文章. Jav ...

  6. java 8 - java 17 升级指北

    2014年发布的java SE 8和2017年发布的java EE 8,至今还是使用最广泛的java版本,大部分java开发者对于java 8之后的升级总是敬而远之,这跟java 9以后的破坏性升级和 ...

  7. Java 11 新功能来了!

    关键时刻,第一时间送达! 目前 Oracle 已经发布了 Java Development Kit 10,下个版本 JDK 11 也即将发布.本文介绍 Java 11 的新功能. 根据Oracle新出 ...

  8. Java 11新功能抢先了解

    目前 Oracle 已经发布了 Java Development Kit 10,下个版本 JDK 11 也即将发布.本文介绍 Java 11 的新功能. 根据Oracle新出台的每6个月发布一次Jav ...

  9. Docker 1.12.0将要发布的新功能

    Docker 1.12.0将要发布的新功能 导读 按计划,6/14 是1.12.0版本的 feature冻结 的日子,再有两个星期Docker 1.12.0也该发布了.这里列出来的新功能,都是已经合并 ...

随机推荐

  1. Redis之集群

    Redis Cluster是 Redis的分布式解决方案,在3.0版本正式推出,有效地解决了Redis分布式方面的需求.当遇到单机内存.并发.流量等瓶颈时,可以采用Cluster架构方案达到负载均衡的 ...

  2. MySQL原理 - InnoDB引擎 - 行记录存储 - Off-page 列

    本文基于 MySQL 8 在前面的两篇文章,我们分析了 MySQL InnoDB 引擎的两种行记录存储格式: Compact 格式 Redundant 格式 在这里简单总结下: Compact 格式结 ...

  3. gitlab 设置tag保护及取消tag保护功能

    用gitlab管理员登录系统 进入项目->设置->Repository 设置项目的Tag保护 效果展示 取消Tag保护 效果展示

  4. AcWing 237. 程序自动分析

    #include<bits/stdc++.h> using namespace std; const int N=1e6+5; int f[N*2],a[N],b[N],c[N],n,t, ...

  5. HTTP:Java实现HTTP请求的三种方式

    目前JAVA实现HTTP请求的方法用的最多的有两种: 一种是通过HTTPClient这种第三方的开源框架去实现.HTTPClient对HTTP的封装性比较不错,通过它基本上能够满足我们大部分的需求,H ...

  6. vuejs知识总结

    1.Vue.js是当下很火的一个JavaScript MVVM库,它是以数据驱动和组件化的思想构建的.ViewModel是Vue.js的核心,它是一个Vue实例. <!DOCTYPE html& ...

  7. Docker原理:Namespace

    目录 Namespace UTS Namespae PID Namespace Mount Namespace User Namespace Network Namespace 参考 Namespac ...

  8. 如果面试官问你 JVM,额外回答逃逸分析技术会让你加分!

    我是陈皮,一个在互联网 Coding 的 ITer,微信搜索「陈皮的JavaLib」第一时间阅读最新文章. 引言 我在面试别人的过程中,JVM 内存模型我几乎必问,虽然有人说问这些就是面试造航母,工作 ...

  9. Linux | 搜索命令

    grep grep 命令用于在文本中执行关键词搜索,并显示匹配的结果,格式:grep[选项][文本] grep命令的参数及其作用 参数 作用 -b 将可执行文件当作文本文件对待 -c 公显示找到的行数 ...

  10. 等了半年,m1芯片原生支持的.NET IDE出现了

    m1芯片是苹果2020年发布的一款基于arm的桌面芯片,目前已经应用在MacBook Air .MacBook Pro.IMac.Ipad等设备上.可以说整个苹果生态圈都在去intel化. 今年年初跟 ...