JDK 13 新特性

oracle官网 jdk-13.0.2_windows-x64 立即下载

Java13概述

2019 年 9 月 17 日,国际知名的 OpenJDK 开源社区发布了 Java 编程语言环境的最新版本 OpenJDK13。

根据 Oracle 的统计信息,如上图所示,在所有为社区 JDK 13 有代码贡献的公司中,排名前五的为:Oracle、Red Hat、SAP、Google 和龙芯。龙芯位列全球第 5,全国第 1,为社区贡献了几十个 Patch。
Features:总共有 5 个新的 JEP(JDK Enhancement Proposals):http://openjdk.java.net/projects/jdk/13/。
各个 build 的更新说明可以查看:https://jdk.java.net/13/release-notes。
Features

  • 350:Dynamic CDS Archives 动态 CDS 档案
  • 351:ZGC: Uncommit Unused Memory ZGC 取消使用未使用的内存
  • 353:Reimplement the Legacy Socket API 重新实现旧版套接字 API
  • 354:Switch Expressions (Preview) Switch 表达式(预览)
  • 355:Text Blocks (Preview) 文字块(预览)

Switch表达式(预览)

在 JDK 12 中引入了 Switch 表达式作为预览特性。JDK 13 提出了第二个 Switch 表达式预览。JEP 354 修改了这个特性,它引入了 yield 语句,用于返回值。这意味着,Switch 表达式(返回值)应该使用 yield,Switch 语句(不返回值)应该使用 break。
在 JDK 12 中有一个,但是要进行一个更改:要从 Switch 表达式中生成一个值 break,要删除 with value 语句以支持 a yield 声明。目的是扩展,Switch 以便它可以用作语句或表达式,因此两个表单既可以使用 case … : 带有连贯符号的传统标签,也可以使用新 case … -> 标签,而不需要通过,还有一个新的语句用于从 Switch 表达式中产生值。这些更改将简化编码并为模式匹配做好准备。
在以前,我们想要在 Switch 中返回内容,还是比较麻烦的,一般语法如下:

@Test
public void testSwitch1(){
    String x = "3";
    int i;
    switch (x) {
        case "1":
            i = 1;
            break;
        case "2":
            i = 2;
            break;
        default:
            i = x.length();
            break;
    }
    System.out.println(i);
}

在 JDK13 中使用以下语法:

@Test
public void testSwitch2(){
    String x = "3";
    int i = switch (x) {
        case "1" -> 1;
        case "2" -> 2;
        default -> {
            yield 3;
        }
    };
    System.out.println(i);
}

或者

@Test
public void testSwitch3() {
    String x = "3";
    int i = switch (x) {
        case "1":
            yield 1;
        case "2":
            yield 2;
        default:
            yield 3;
    };
    System.out.println(i);
}

在这之后,Switch 中就多了一个关键字用于跳出 Switch 块了,那就是 yield,他用于返回一个值。和 return 的区别在于:return 会直接跳出当前循环或者方法,而 yield 只会跳出当前 Switch 块。

文本块(预览)

在 JDK 12 中引入了 Raw String Literals 特性,但在发布之前就放弃了。这个 JEP 与引入多行字符串文字(text block)在意义上是类似的。
这条新特性跟 Kotlin 里的文本块是类似的。

现实问题

在 Java 中,通常需要使用 String 类型表达 HTML,XML,SQL 或 JSON 等格式的字符串,在进行字符串赋值时需要进行转义和连接操作,然后才能编译该代码,这种表达方式难以阅读并且难以维护。
文本块就是指多行字符串,例如一段格式化后的 xml、json 等。而有了文本块以后,用户不需要转义,Java 能自动搞定。因此,文本块将提高 Java 程序的可读性和可写性。

目标

  • 简化跨越多行的字符串,避免对换行等特殊字符进行转义,简化编写 Java 程序
  • 增强 Java 程序中字符串的可读性

举例

会被自动转义,如有一段以下字符串:

<html>
    <body>
        <p>Hello, Java13</p>
    </body>
</html>

将其复制到 Java 的字符串中,会展示成以下内容:

"<html>\n" +
    " <body>\n" +
    	" <p>Hello, Java13</p>\n" +
    " </body>\n" +
"</html>\n";

上面内容被自动进行了转义,这样的字符串看起来不是很直观,在 JDK 13 中,就可以使用以下语法了:

"""
<html>
    <body>
    	<p>Hello, Java13</p>
    </body>
</html>
""";

使用 “”" 作为文本块的开始符和结束符,在其中就可以放置多行的字符串,不需要进行任何转义。看起来就十分清爽了。
如常见的 SQL 语句:

select employee_id,last_name,salary,department_id
from employees
where department_id in (40,50,60)
order by department_id asc

原有方式:

String query = "select employee_id,last_name,salary,department_id\n" +
            "from employees\n" +
            "where department_id in (40,50,60)\n" +
            "order by department_id asc";

使用新特性:

String newQuery = """
    select employee_id,last_name,salary,department_id
    from employees
    where department_id in (40,50,60)
    order by department_id asc
""";

具体使用

内容看不懂,可以看视频讲解:

  • https://www.bilibili.com/video/BV1jJ411M7kQ?p=27
  • https://www.bilibili.com/video/BV1jJ411M7kQ?p=28

基本使用

  • 文本块是 Java 语言中的一种新文字。它可以用来表示任何字符串,并且提供更大的表现力和更少的复杂性
  • 文本块由零个或多个字符组成,由开始和结束分隔符括起来
    • 开始分隔符是由三个双引号字符(“”"),后面可以跟零个或多个空格,最终以行终止符结束。文本块内容以 开始分隔符的行终止符后的第一个字符开始
    • 结束分隔符也是由三个双引号字符(“”")表示,文本块内容以 结束分隔符的第一个双引号之前的最后一个字符结束
  • 文本块中的内容可以直接使用 “,”,但不是必需的
  • 文本块中的内容可以直接包括行终止符。允许在文本块中使用 \n,但不是必需的。

例如,文本块:

"""
line1
line2
line3
"""

相当于:

"line1\nline2\nline3\n"

或者一个连接的字符串:

"line1\n" +
"line2\n" +
"line3\n"

如果字符串末尾不需要行终止符,则结束分隔符可以放在最后一行内容上。例如:

"""
line1
line2
line3"""

相当于(line3 少了 \n)

"line1\nline2\nline3"

文本块可以表示空字符串,但不建议这样做,因为它需要两行源代码:

String empty = """
""";

以下示例是错误格式的文本块:

String a = """"""; // 开始分隔符后没有行终止符
String b = """ """; // 开始分隔符后没有行终止符
String c = """
			"; // 没有结束分隔符
String d = """
            abc \ def
            """; // 含有未转义的反斜线(请参阅下面的转义处理)

在运行时,文本块将被实例化为 String 的实例,就像字符串一样。从文本块派生的 String 实例与从字符串派生的实例是无法区分的。具有相同内容的两个文本块将引用相同的 String 实例,就像字符串一样。
编译器在编译时会删除掉这些多余的空格
下面这段代码中,我们用 . 来表示我们代码中的的空格,而这些位置的空格就是多余的。

String html = """
..............<html>
.............. <body>
.............. <p>Hello, world</p>
.............. </body>
..............</html>
..............""";

多余的空格还会出现在每一行的结尾,特别是当你从其他地方复制过来时,更容易出现这种情况,比如下面的代码:

String html = """
..............<html>...
.............. <body>
.............. <p>Hello, world</p>....
.............. </body>.
..............</html>...
..............""";

这些多余的空格对于程序员来说是看不到的,但是他又是实际存在的,所以 如果编译器不做处理,可能会导致程序员看到的两个文本块内容是一样的,但是这两个文本块却因为存在这种多余的空格而导致差异,比如哈希值不相等。
所以编译器在编译时会删除掉这些多余的空格,但是有个细节:

  • 如果是字符串后面的空格,则无条件删除
  • 如果是字符串前面的空格,那就看结束分隔符的空格数
    • 如果结束分隔符没有空格,则不会删除字符串前面的空格
    • 如果结束分隔符有 n 个空格,则删除字符串前面的 n 个空格

例如:

// 如果结束分隔符 """ 没有空格,则不会删除字符串前面的空格
String str = """
 hello 
"""
System.out.println(str.length()); // 6

// 如果结束分隔符 """ 有 n 个空格,则删除字符串前面的 n 个空格
String str1 = """
 hello  
 """
System.out.println(str1.length()); // 5

转义字符
允许开发人员使用 \n,\f 和 \r 来进行字符串的垂直格式化,使用 \b 和 \t 进行水平格式化。比如下面的代码是合法的(输出的效果会额外被转义字符改变):

String html = """
    <html>\n
        <body>\n
        	<p>Hello, world</p>\n
        </body>\n
    </html>\n
""";

请注意,在文本块内自由使用 " 是合法的。例如(输出带有 “” 的内容):

String story = """
    "When I use a word," Humpty Dumpty said,
    in rather a scornful tone, "it means just what I
    choose it to mean - neither more nor less."
    "The question is," said Alice, "whether you
    can make words mean so many different things."
    "The question is," said Humpty Dumpty,
    "which is to be master - that's all."
""";

但是,三个 " 字符的序列需要进行转义至少一个 ",以避免模仿结束分隔符:

String code =
    """
    String text = \"""
    	A text block inside a text block
    \""";
    """;

文本块连接
可以在任何可以使用字符串的地方使用文本块。例如,文本块和字符串可以相互连接:

String code = "public void print(Object o) {" +
            """
                System.out.println(Objects.toString(o));
                }
            """;

但是,涉及文本块的连接可能变得相当笨重。以下面文本块为基础:

String code = """
    public void print(Object o) {
    	System.out.println(Objects.toString(o));
    }
""";

假设我们想把上面的 Object 改为来自某一变量 type,我们可能会这么写:

String code = """
    public void print(""" + type + """
    o) {
    	System.out.println(Objects.toString(o));
    }
""";

可以发现这种写法可读性是非常差的,更简洁的替代方法是使用 String :: replace 或 String :: format,比如:

String code = """
    public void print($type o) {
    	System.out.println(Objects.toString(o));
    }
""".replace("$type", type);

或

String code = String.format("""
    public void print(%s o) {
    	System.out.println(Objects.toString(o));
    }
""", type);

另一个方法是使用 String :: formatted,这是一个新方法,比如:

String source = """
    public void print(%s object) {
    	System.out.println(Objects.toString(object));
    }
""".formatted(type);

动态CDS档案(动态类数据共享归档)

CDS,是 Java 12 的特性了,可以让不同 Java 进程之间共享一份类元数据,减少内存占用,它还能加快应用的启动速度。而 JDK13 的这个特性支持在 Java Application 执行之后进行动态 archive。存档类将包括默认的基础层 CDS 存档中不存在的所有已加载的应用程序和库类。也就是说,在 Java 13 中再使用 AppCDS 的时候,就不再需要这么复杂了。
该提案处于目标阶段,旨在提高 AppCDS 的可用性,并消除用户进行试运行以创建每个应用程序的类列表的需要。
使用示例:

# JVM 退出时动态创建共享归档文件:导出 jsa
java -XX:ArchiveClassesAtExit=hello.jsa -cp hello.jar Hello

# 用动态创建的共享归档文件运行应用:使用 jsa
java -XX:SharedArchiveFile=hello.jsa -cp hello.jar Hello

ZGC:取消使用未使用的内存

G1和Shenandoah

JVM 的 GC 释放的内存会还给操作系统吗?
GC 后的内存如何处置,其实是取决于不同的垃圾回收器。因为把内存还给 OS,意味着要调整 JVM 的堆大小,这个过程是比较耗费资源的。

HotSpot 的 G1 和 Shenandoah 这两个 GC 已经提供了这种能力,并且对某些用户来说,非常有用。因此,Java13 则给 ZGC 新增归还 unused heap memory 给操作系统的特性。

ZGC的使用背景

在 JDK 11 中,Java 引入了 ZGC,这是一款可伸缩的低延迟垃圾收集器,但是当时只是实验性的。号称不管你开了多大的堆内存,它都能保证在 10 毫秒内释放 JVM ,不让它停顿在那。但是,当时的设计是它不能把内存归还给操作系统。对于比较关心内存占用的应用来说,肯定希望进程不要占用过多的内存空间了,所以这次增加了这个特性。

在 Java 13 中,JEP 351 再次对 ZGC 做了增强,将没有使用的堆内存归还给操作系统。ZGC 当前不能把内存归还给操作系统,即使是那些很久都没有使用的内存,也只进不出。这种行为并不是对任何应用和环境都是友好的,尤其是那些内存占用敏感的服务,例如:

  • 按需付费使用的容器环境
  • 应用程序可能长时间闲置,并且和很多其他应用共享和竞争资源的环境
  • 应用程序在执行期间有非常不同的堆空间需求,例如,可能在启动的时候所需的堆比稳定运行的时候需要更多的堆内存

使用细节

ZGC 的堆由若干个 Region 组成,每个 Region 被称之为 ZPage。每个 Zpage 与数量可变的已提交内存相关联。当 ZGC 压缩堆的时候,ZPage 就会释放,然后进入 Page Cache,即 ZPageCache。这些在 Page Cache 中的 ZPage 集合就表示没有使用部分的堆,这部分内存应该被归还给操作系统。回收内存可以简单的通过从 Page Cache 中逐出若干个选好的 ZPage 来实现,由于 Page Cache 是以 LRU(Least recently used,最近最少使用)顺序保存 ZPage 的,并且按照尺寸(小,中,大)进行隔离,因此逐出 ZPage 机制和回收内存相对简单了很多,主要挑战是设计关于何时从 Page Cache 中逐出 ZPage 的策略。
一个简单的策略就是设定一个超时或者延迟值,表示 ZPage 被驱逐前,能在 Page Cache 中驻留多长时间。这个超时时间会有一个合理的默认值,也可以通过 JVM 参数覆盖它。Shenandoah GC 用了一个类型的策略,默认超时时间是 5 分钟,可以通过参数 -XX:ShenandoahUncommitDelay = milliseconds 覆盖默认值。
像上面这样的策略可能会运作得相当好。但是,用户还可以设想更复杂的策略:不需要添加任何新的命令行选项。例如,基于 GC 频率或某些其他数据找到合适超时值的启发式算法。JDK13 将使用哪种具体策略目前尚未确定。可能最初只提供一个简单的超时策略,使用 -XX:ZUncommitDelay = seconds 选项,以后的版本会添加更复杂、更智能的策略(如果可以的话)。
uncommit 能力默认是开启的,但是无论指定何种策略,ZGC 都不能把堆内存降到低于 Xms。这就意味着,如果 Xmx 和 Xms 相等的话,这个能力就失效了。-XX:-ZUncommit 这个参数也能让这个内存管理能力失效。

重新实现旧版套接字API

现有问题

重新实现了古老的 Socket 接口。现在已有的 java.net.Socket 和 java.net.ServerSocket 以及它们的实现类,都可以回溯到 JDK 1.0 时代了。

  • 它们的实现是混合了 Java 和 C 的代码的,维护和调试都很痛苦
  • 实现类还使用了线程栈作为 I/O 的缓冲,导致在某些情况下还需要增加线程栈的大小
  • 支持异步关闭,此操作是通过使用一个本地的数据结构来实现的,这种方式这些年也带来了潜在的不稳定性和跨平台移植问题。该实现还存在几个并发问题,需要彻底解决

在未来的网络世界,要快速响应,不能阻塞本地方法线程,当前的实现不适合使用了。

新的实现类

全新实现的 NioSocketImpl 来替换 JDK1.0 的 PlainSocketImpl。

  • 它便于维护和调试,与 NewI/O(NIO)使用相同的 JDK 内部结构,因此不需要使用系统本地代码
  • 它与现有的缓冲区缓存机制集成在一起,这样就不需要为 I/O 使用线程栈
  • 它使用 java.util.concurrent 锁,而不是 synchronized 同步方法,增强了并发能力
  • 新的实现是 Java 13 中的默认实现,但是旧的实现还没有删除,可以通过设置系统属性 jdk.net.usePlainSocketImpl 来切换到旧版本

代码说明

运行一个实例化 Socket 和 ServerSocket 的类将显示这个调试输出。这是默认的(新的)。

Module java.base
    Package java.net
    Class SocketImpl
    public abstract class SocketImpl implements SocketOptions {
        private static final boolean USE_PLAINSOCKETIMPL = usePlainSocketImpl();
        private static boolean usePlainSocketImpl() {
            PrivilegedAction<String> pa = () ->
                NetProperties.get("jdk.net.usePlainSocketImpl");
            String s = AccessController.doPrivileged(pa);
            return (s != null) && !s.equalsIgnoreCase("false");
        }
        /**
* Creates an instance of platform's SocketImpl
*/
        @SuppressWarnings("unchecked")
        static <S extends SocketImpl & PlatformSocketImpl> S createPlatformSocketImpl(boolean server) {
            if (USE_PLAINSOCKETIMPL) {
                return (S) new PlainSocketImpl(server);
            } else {
                return (S) new NioSocketImpl(server);
            }
        }
    }

SocketImpl 的 USE_PLAINSOCKETIMPL 取决于 usePlainSocketImpl 方法,而它会从 NetProperties 读取 dk.net.usePlainSocketImpl 配置,如果不为 null 且不为 false,则 usePlainSocketImpl 方法返回 true;createPlatformSocketImpl 会根据 USE_PLAINSOCKETIMPL 来创建 PlainSocketImpl 或者 NioSocketImpl。

其他解读

上面列出的是大方面的特性,除此之外还有一些 API 的更新及废弃,主要见 JDK 13 Release Notes:https://jdk.java.net/13/release-notes
这里举几个例子。

增加项

  • 添加 FileSystems.newFileSystem(Path, Map) Method
  • 新的 java.nio.ByteBuffer:Bulk get/put Methods Transfer Bytes Without Regard to Buffer Position
  • 支持 Unicode 12.1
  • 添加 -XX:SoftMaxHeapSize Flag,目前仅仅对 ZGC 起作用
  • ZGC 的最大 heap 大小增大到 16TB

移除项

  • 移除 awt.toolkit System Property
  • 移除 Runtime Trace Methods
  • 移除 -XX:+AggressiveOpts
  • 移除 Two Comodo Root CA Certificates、Two DocuSign Root CA Certificates
  • 移除内部的 com.sun.net.ssl 包

废弃项

  • 废弃 -Xverify:none 及 -noverify
  • 废弃 rmic Tool,并准备移除
  • 废弃 javax.security.cert,并准备移除

已知问题

  • 不再支持 Windows 2019 Core Server
  • 使用 ZIP File System (zipfs) Provider 来更新包含 Uncompressed Entries 的 ZIP 或 JAR 可能造成文件损坏

其他事项

  • GraphicsEnvironment.getCenterPoint() 及 getMaximumWindowBounds() 已跨平台统一
  • 增强了 JAR Manifest 的 Class-Path 属性处理
  • 针对 Negatively Sized Argument,StringBuffer(CharSequence) 及 StringBuilder(CharSequence)会抛出 NegativeArraySizeException
  • Linux 的默认进程启动机制已经使用 posix_spawn
  • Lookup.unreflectSetter(Field) 针对 static final fields 会抛出 IllegalAccessException
  • 使用了 java.net.Socket.setSocketImplFactory 及 java.net.ServerSocket.setSocketFactory 方法的要注意,要求客户端及服务端要一致,不能一端使用自定义的 factory 一端使用默认的 factory
  • SocketImpl 的 supportedOptions、getOption 及 setOption 方法的默认实现发生了变化,默认的 supportedOptions 返回空,而默认的 getOption 及 setOption 方法抛出 UnsupportedOperationException
  • JNI NewDirectByteBuffer 创建的 Direct Buffer 为 java.nio.ByteOrder.BIG_ENDIAN
  • Base64.Encoder 及 Base64.Decoder 可能抛出 OutOfMemoryError
  • 改进了 Serial GC 的 Young pause time report
  • 改进了 MaxRAM 及 UseCompressedOops 参数的行为

小结

以上,就是 JDK13 中包含的主要特性。

  • 语法层面,改进了 Switch Expressions,新增了 Text Blocks,二者皆处于 Preview 状态
  • API 层面主要使用 NioSocketImpl 来替换 JDK1.0 的 PlainSocketImpl
  • GC 层面则改进了 ZGC,以支持 Uncommit Unused Memory

而且,JDK13 并不是 LTS(长期支持)版本,如果你正在使用 Java 8(LTS)或者 Java 11(LTS),暂时可以不必升级到 Java 13。
这些年很多 Java 粉丝已经讨厌写那些冗长难看的代码了,有些转投到高效的 Python 门下,有的转用 Kotlin,有的去了新兴的 Go 那边。不过,Java 大叔凭着其广阔的领土,活跃高效的运转机构,以及其开放改革的心,还会有不少的粉丝追随他的。

采用新版本的注意事项

在采用新版本 Java 之前必须考虑的一些注意事项/风险。

注意1:被新版本系列绑架

如果采用了 Java 12 并使用新的语言特性或新的 API,这意味着实际上你已将项目绑定到 Java 的新版本系列。接下来你必须采用 Java 13、14、15、16 和 17。
使用了新版本,每个版本的使用寿命为六个月,并且在发布后仅七个月就过时了。这是因为每个版本只有在六个月内提供安全补丁,发布后 1 个月的第一个补丁和发布后 4 个月的第二个补丁。7 个月后,下一组安全补丁会发布,但旧版本不能获取更新。
因此,你要判断自身的开发流程是否允许升级 Java 版本,一个月的时间窗口方面会不会太狭窄?或者你是否愿意在安全基线以下的 Java 版本上运行?

注意2:升级的绊脚石

实际使用中有很多阻止我们升级 Java 的因素,下面列出一些常见的:

  • 开发资源不足:你的团队可能会非常忙碌或规模太小,你能保证两年后从 Java 15 升级到 16 的开发时间吗
  • 构建工具和 IDEA:使用的 IDEA 是否会在发布当天支持每个新版本?Maven? Gradle 呢? 如果不是,你有后备计划吗?请记住,你只有 1 个月的时间来完成升级、测试并将其发布到生产环境中。此外还包括 Checkstyle, JaCoCo,PMD,SpotBugs 等等其他工具
  • 依赖关系:你的依赖关系是否都准备好用于每个新版本?请记住,它不仅仅是直接依赖项,而是技术堆栈中的所有内容。字节码操作库尤其受到影响,例如 ByteBuddy 和 ASM
  • 框架:这是另一种依赖,但是一个大而重要的依赖。在一个月的狭窄时间窗口内,Spring 会每六个月发布一个新版本吗?Jakarta EE(以前的 Java EE)会吗?如果它们不这样做会怎么样

现在,任何阻挡者的传统方法都是等待:在开始升级之前等待 6 到 12 个月,以便为工具,库和框架提供修复任何错误的机会。

注意3:云/托管/部署

你是否可以控制代码在生产环境中的运行位置和方式?例如,如果你在 AWS(Amazon Web Service) Lambda 中运行代码,则无法控制。AWS Lambda 没有采用 Java 9 或 10,甚至没有采用 Java 11。所以除非 AWS 提供公共保证以支持每个新的 Java 版本,否则根本无法采用 Java 12。(我的工作假设是 AWS Lambda 仅支持主要的 LTS 版本,由 Amazon Corretto JDK 公告支持 (opens new window)。)
如何托管你的 CI 系统?Jenkins、Travis、Circle、Shippable、GitLab 会快速更新吗?如果不是,你会怎么做?

注意4:为采用新版本进行规划

如果正在考虑采用新版本的 Java,建议你准备一份现在所依赖的所有内容的清单,或者可能在未来 3 年内会依赖的。你需要保证该列表中的所有内容都能正常工作,并与新版本一起升级,或者如果该依赖项不再更新,请制定好计划。以某位互联网开发者为例,他列的清单如下:

  • Amazon AWS
  • Eclipse
  • IntelliJ
  • Travis CI
  • Shippable CI
  • Maven
  • Maven 插件(compile、jar、source、javadoc 等)
  • Checkstyle,以及相关的 IDE 插件和 Maven 插件
  • JaCoCo,以及相关的 IDE 插件和 Maven 插件
  • PMD 和相关的 Maven 插件
  • SpotBugs 和相关的 Maven 插件
  • OSGi bundle metadata tool
  • Bytecode 工具(Byte buddy / ASM etc)
  • 超过 100 个 jar 包依赖项

说了这么多,当然不是鼓励大家不进行升级,新语言特性带来的好处以及性能增强会让开发者受益,但升级背后的风险也应该考虑进去。

注意5:其他第三方厂商的声明

Spring 框架已经在视频中表达了对 Java 12 的策略。关键部分是(Spring 官方声明):

  • Java 8 和 11 作为 LTS 版本会持续获得我们的正式支持,对于过渡版本,我们也会尽最大努力支持,但它们不会获得正式的生产环境支持。如果你升级到 Java 11,我们非常愿意和你合作,因为长期支持版本才是我们关注的重心,对于 Java 12 及更高版本我们会尽最大的努力

作为典型软件供应商的一个例子,Liferay 声明如下:

  • Liferay 已决定不会对 JDK 的每个主要版本进行认证。我们将选择遵循 Oracle 的主导并仅认证标记为 LTS 的版本

个人的想法:

  • 想象一下汽车制造商的类似行为:
    • 每 6 个月重新设计和发布一次汽车
    • 从 2018 年开始,每三年只提供一次完整的保修
    • 如果客户购买 2019 型号并且在 6 个月内出现问题,他们必须等待并购买 2020 修复模型
    • 2020 型号是电动的,但你的城镇的基础设施还不支持电充等设备支持,更不用说座椅已经改变并导致腰痛
    • 不用担心,购买 2020.3 型号

最后

再谈JDK版本更新


在 Java 9 之前,当一个版本被宣布为首选版本,存在一个「培育」(bedded-in)新 GA 版本的重叠期。在此期间,上一个版本将会继续进行免费更新。为确保新旧版本间的干净切换,即便旧版本已不再是首选版本,通常也会继续维护 12 个月以上。但是 随着 Java 版本发布更改为遵循严格的时间表后,事实上宣告了传统的免费支持期将寿终正寝。
也许不会有太多公司直接选择 JDK12、JDK 13,但个别的生产实践并不遥远。比如,实际工作场景中,利用 JDK 12 的 Abortable Mixed Collections for G1,解决了 HDFS 在特定场景中 G1 Evacuation 时间过长的困扰,虽然最后团队选择将其 backport 到了自己的 JDK11 版本中,但如果没有快速交付的预览版 JDK12,也不会如此快速的得到结论。
而对另一个问题,目前看是非常成功的,解开了 Java/JVM 演进的许多枷锁,至关重要的是,OpenJDK 的权力中心,正在转移到开发社区和开发者手中。在新的模式中,既可以利用 LTS 满足企业长期可靠支持的需求,也可以满足各种开发者对于新特性迭代的诉求。你可能注意到了 Switch Expressions 被打上了预览(Preview)的标签, Shenandoah GC 则是实验(Experimental)特性,这些都是以往的发布周期下不大现实的,因为用 2-3 年的最小间隔粒度来实验一个特性,基本是不现实的。
可以预计,JDK8 在未来的一段时间仍将是主流,我们已经注意到 Amazon、Alibaba、Redhat、AdoptOpenJDK 等等厂商或社区,纷纷发布了自己的 JDK8 等产品,开始竞赛长期支持版本 JDK 的主导权,这是非常好的迹象,反映了主流厂商对于 Java 的投资力度增大。
是否会带来 Java/JVM 的碎片化呢?多少会发生一些,但从目前的合作模式来看,OpenJDK 仍然是合作的中心,主导这 Java 历史版本维护和未来的演进路线。

Oracle撒手,OpenJDK继续向前

Java 8 是目前使用率最高的一个 Java 版本,发布于 2014 年,而 Oracle 对 Java 8 的官方支持时间持续到 2020 年 12 月,之后将不再为个人桌面用户提供 Oracle JDK 8 的修复更新;在 2019 年 1 月之后,不再提供免费的商业版本更新,届时想要继续获得 Oracle 的商业支持和维护,需付费订阅。
近日,Oracle 的销售代表发出的一封邮件引起了热议,该邮件称「Java 8 的非公开可用的关键补丁更新」将于 2019 年 4 月 16 日发布,拥有有效许可证的客户才可以享用。邮件继续称,如果没有安装这些更新,可能导致「你的服务器和桌面环境暴露且易受攻击」。
但在许多 Java 用户看来,这封邮件像是一种敲诈勒索或恐吓策略。

虽然 Oracle 官方选择了不再支持,但 Java 社区却把担子接了下来。红帽 Java 平台团队的首席工程师 Andrew Haley 曾表示,红帽计划在 2023 年之前继续提供对 OpenJDK 8 的支持:

  • 在我看来,这算比较正常的。几年前,OpenJDK 6 更新(JDK6u)项目被 Oracle 放弃,我接管了它,然后 OpenJDK 7 也发生了同样的事情。最后,Azul 的 Andrew Brygin 接管了 OpenJDK 6。由来自多个组织成员组成的 OpenJDK Vulnerability Group 就重要的安全问题进行协作。在广大的 OpenJDK 社区和我的团队(Red Hat)的帮助下,我们定期为关键 Bug 和安全漏洞提供更新。我觉得这样的过程同样适用于 OpenJDK 8 和下一个长期支持版本,即 OpenJDK 11。如果可以得到社区的支持,我很高兴能够领导 JDK 8 更新项目和 JDK 11 更新项目

除了红帽以外,AWS 推出了 OpenJDK 长期支持版本 Amazon Corretto。阿里巴巴也开源了 OpenJDK 长期支持版本 Alibaba Dragonwell。

未来展望

Java 的变化速度从未如此之快——如今,该语言的新版本每六个月就会发布一次。
而之所以能够实现如此重大的转变,自然离不开一系列专注于 提高其性能 与 添加新功能 的协作性项目的贡献。这些项目的目标可谓雄心勃勃。正如 JetBrains 开发者布道师 Trisha Gee 在 QCon 伦敦 2019 大会上所言:Java 即将迎来很多超酷的东西。
而发展道路中的以下三大主要项目,将有助于确定 Java 的未来方向。
项目一:Loom 项目
尝试改进 Java 语言的并发处理方式,或者说是在对计算机在不同指令集执行之间切换能力的探索。
甲骨文公司 Loom 项目技术负责人 Ron Pressler 在 QCon 伦敦 2019 大会上向希望编写软件以处理并发任务的 Java 开发者们提出了两种都不够完美的选项:要么编写无法通过扩展处理大量并发任务的「简单同步阻塞代码」,要么编写可扩展但编写难度极高且调试过程复杂的异步代码。
为了寻求解决这个问题的方法,Loom 项目引入了一种将任务拆分为线程的新方法——所谓线程,即是指计算机在运行指令时的最小可能执行单元。在这方面,Loom 引入了被称为 fibers 的新型轻量级用户线程。
他在大会上指出:利用 fibers,如果我们确保其轻量化程度高于内核提供的线程,那么问题就得到了解决。大家将能够尽可能多地使用这些用户模式下的轻量级线程,且基本不会出现任何阻塞问题。
利用这些新的 fibers,用户将能够扩展 Java 虚拟机(JVM)以支持定界延续(delimited continuations)机制,从而使得指令集的执行实现暂停以及恢复。对这些延续进行暂停与恢复的任务将由 Java 中的 ForkJoinPool 调度程序以异步模式处理。
根据说明文档所言,fibers 将使用与 Java 现有 Thread 类非常相似的 API,这意味着 Java 开发人员的学习曲线应该不会太过陡峭。
项目二:Amber 项目
Amber 项目的目标,在于 支持「更小、面向生产力的 Java 语言功能」的开发,从而加快将新功能添加至 Java 语言中的速度。
这套方案非常适合自 Java 9 以来,以更快速度持续发布的各 Java 新版本。
目前,以下 JDK 增强提案(简称 JEP)正在进行当中,并隶属于 Amber 项目之内。
生字符串
生字符串使得开发人员能够更轻松地对文本进行适当格式化,且无需引入由转义字符带来的复杂性。
举例来说,开发人员不必使用转义字符来表示换行符,因此在以下字符串中:

Hello World

可以直接编写为:

`Hello World`

而非原本的:

"Hello World"

该提案的说明文档中提到,这一变更将使得各类文本客串的输入变得更加简单,包括文件路径以及 SQL 语句等等。
如大家所见,生字符串应被包含在反引号之内。
用于 JDK API 的 Java 编译器 Intrinsic:https://openjdk.java.net/jeps/348。此项提案将允许开发人员对需要定期调用的重要代码段进行性能优化。
Pattern Matching
官网介绍地址:https://openjdk.java.net/jeps/305。
Pattern Matching 能够简化利用 Java 中 instanceof 运算符检查对象是否属于特定类的过程,而后提取该对象的组件以进行进一步处理。
如此一来,以下操作语法:

if (obj instanceof Integer) { int intValue = ((Integer) obj).intValue(); // use
intValue }

将可被简化为:

if (x instanceof Integer i) { // can use i here, of type Integer }

Switch Expressions
官网介绍地址:https://openjdk.java.net/jeps/325。
Switch expressions 已经在 Java 12 当中以预览版形式推出,允许开发人员利用更简单的语法通过 Switch 语句为输入内容指定不同的响应方式。
举例来说,现在我们不再需要始终在以下语法当中使用 Switch 语句:

switch (port) { case 20: type = PortType.FTP; break; }

而可以采取以下更为简洁的表达方式:

Switch (port) { case 20 -> PortType.FTP; }

项目三:Valhalla 项目
Valhalla 项目专注于支持高级 JVM 与语言功能的开发。
目前 Valhalla 项目的候选提案还比较有限,具体包括:
Value Types
官网介绍地址:https://openjdk.java.net/jeps/169。
此项提案旨在允许 JVM 处理一种新的类型,即 Value Types。
这些新的不可变类型将拥有与 int 等基元类似的内存效率,但同时又与普通类一样能够保存一整套基元集合。提案说明文档中指出,其目标在于「为 JVM 基础设施提供处理不可变与无引用对象的能力,从而实现使用非基元类型进行高效按值计算的目标。」
Generic Specialization
官网介绍地址:https://openjdk.java.net/jeps/218。
此项提案 扩展了适用于泛型的具体类型,其中包括基元以及即将推出的 Value Types。

解决用加速器以后,电脑无法连接网络的问题 相信很多朋友也遇到过,用加速器以后,电脑网络直接断了,或者访问外网时打不开的情况解决办法是。 阅读详情

相关推荐

不刷机!Jetson AGX Orin无损更新内核与设备树的两种安全方法(附备份恢复脚本)

本文详细介绍了Jetson AGX Orin在不刷机的情况下安全更新内核与设备树的两种方法,包括extlinux.conf动态加载和分区精准刷新方案。通过备份恢复脚本和工业级灾备方案,确保零数据丢失,适用于边缘AI和机器人等关键场景。

weixin_40192258的博客 307

JDK13的六大重要新特性

JDK13的六大重要特性 JDK13在9月17号全球首发了,Oracle JDK 13通过改善Java SE平台和JDK的性能,稳定性和安全性来提高开发人员的生产力。这次的JDK13包含了5个JEP(Java Enhancement Proposals)和一个Unicode 12.1的支持总共6大主要新特性。下面我们一一详细说明。 支持Unicode 12.1 动态CDS归档(Dynamic CDS Archiving) java.net.Socket和java.net.ServerSocket API的

m0_68064743的博客 1217

AOSP14 Launcher3——手势上滑关键类AbsSwipeHandler解析

通过精密的事件监听、状态管理和对系统动画 API 及 Launcher 内部组件的协调,实现了复杂而流畅的手势导航体验。它的抽象设计允许子类(如。是 Quickstep (Launcher3 的手势导航实现) 中处理。的核心逻辑抽象基类。这个非常核心且复杂的类。)定制特定的回家动画逻辑。好的,我们来深入分析。

Micheal_Yang's Blog 1519

JDK 13 新特性一览

1、switch优化更新 JDK11以及之前的版本: switch(day){ caseMONDAY: caseFRIDAY: caseSUNDAY: System.out.println(6); break; caseTUESDAY: System.out.println(7); ...

Java笔记虾 1912

RseQC实战指南:从安装到RNA-Seq数据质控全流程解析

本文提供了一份详尽的RseQC实战指南,涵盖从安装配置到RNA-Seq数据质控的全流程。文章重点解析了RseQC作为专业质控工具的核心价值,手把手指导如何通过Conda或pip完成安装,并深入讲解了bam_stat.py、geneBody_coverage.py等关键模块的使用方法与结果解读技巧,帮助用户有效评估RNA完整性、文库构建质量及链特异性,确保下游分析的可靠性。

weixin_29200741的博客 200

有史以来最小的GIF/png/jpg/jpeg

昨天我对图像进行了 base64 编码,这样我就可以将它发送到 CouchDB 以测试我正在为客户编写的一些代码。它让我想起了我之前在远程服务器上设置 cookie 时所做的事情。基本上,一个小的 PHP 脚本被放在远程服务器上,它接受几个 GET 参数并根据它们的值设置一些 cookie。然后脚本输出一个 1x1 的透明 GIF。本地服务器上的 PHP 脚本生成了一个 IMG 标签,该标签链接到该图像并根据本地服务器上的 COOKIES 设置参数。

凌凌1301的博客 1417

JDK13新特性

JDK13新特性

蓝影铁哥的博客 1791

基于Matlab生成并可视化多架飞机轨迹仿真(附源码)

这使我们可以轻松地对直线和恒定转弯进行建模,并具有额外的自由度,可以在直线段和曲线段之间平滑过渡。同样,空气中的物体会经历重力的影响,遵循抛物线(二次)路径。需要更多的航点来适应这些变化,但是轨迹的其余部分需要更少的点。第三个轨迹,如下所示,代表了一架速度更高的飞机。它由两个恒定的转弯组成,飞机在第二个转弯的中间减速。一旦知道(并设置了)物体穿过空间的物理路径,物体的速度作为行进距离的函数就通过三次埃尔米特插值来确定。在此示例中,学习了内部使用的插值符背后的概念,并展示了如何使用少量航点重现场景。

珞瑜的博客 5463

Java13的主要新特性总结

JDK 13 于2019 年 9 月 17 日正式发布。。JEP(Java Enhancement Proposal)Java增强提案JEP 354这仍然是一个预览特性。Switch 表达式是在 Java 12 中首次作为预览特性引入,而在 Java 13 中对 Switch 表达式做了增强改进:在块中引入了yield语句来返回值,而不是使用break。yield关键字用于从 switch 表达式的 case 块中返回一个值。

donggongai的博客 1030

Claude Code本地Windows安装教程

本文介绍了在Windows系统上安装和配置Claude Code本地调用的详细步骤。首先需要确保网络畅通和账号余额充足,然后安装Node.js v22版本作为基础环境。接着通过npm全局安装Claude Code包,并进行版本验证。安装完成后,使用命令行登录并可以指定模型启动。最后还提供了切换API秘钥的方法,通过setup-token命令重新授权账号。整个过程配有详细的命令行示例和操作截图,方便用户按步骤完成安装配置。

猿小白的博客 2万+

在WIN10系统中安装TIA博途V18,重启后提示安装介质不可用,请插入DVD 或检查网络连接的解决办法

在WIN10系统中安装TIA博途V18,重启后提示安装介质不可用,请插入DVD 或检查网络连接的解决办法

Robot_PLC_HMI_Automation 1万+

java13 新特性

JDK13今日发布,带来5大新特性 JDK JDK作为JAVA的核心,发展至今,已经更新到13版本了。 早在2017年8月,JCP执行委员会就已经提出将JAVA的发布频率修改调整为每六个月一次,新的发布周期将严格遵循这个时间点,每年的3月份和9月份将会发布新的JDK。 今日,JDK13正式发布,在官网上,我们可以看到JDK13的进展情况。 JDK13 可以看到,今日JDK13已...

oldshaui的博客 762

2023 ICRA《Visual Language Maps for Robot Navigation》阅读笔记

视觉语言导航可以使用预先训练的现有的视觉语言模型来将图像与对象目标的自然语言描述相匹配,但它与绘制环境的过程仍然脱节,缺乏经典几何地图的空间精度。为了解决这个问题,我们提出了VLMaps,这是一种空间地图表示,它将预训练的视觉语言特征与物理世界的3D重建直接融合在一起。VLMaps可以使用标准探索方法从机器人上的视频馈送中自主构建,并在没有额外标记数据的情况下实现地图的自然语言索引。具体来说,当与大型语言模型(LLM)相结合时,VLMaps可以用于。

qq_44100524的博客 1990

jdk9、jdk10、jdk11、jdk12、jdk13新特性

我们绝大部分人估计都还在用着jdk8,12其实是一个非LTS(long time support)版本,而11与8一样是LTS版,意味着下个通用的版本将从8直接到11,毕竟11包含了9和10的所有新特性,因此9和10估计就直接被废弃啦。不过9、10、11、12面向开发者的新特性其实并不是很多,大部分都是一些优化、收集器加强以及增加了一些新功能等等 而我们开发人员最为关注的肯定是对我们搬砖有用的特...

一火的专栏 2万+

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

JDK9——JDK13新特性总结

在 JDK 8 中,接口可以有默认方法和静态方法,但无法在接口中添加私有方法,导致代码复用性差,公共逻辑只能放在默认或静态方法中。JDK 9 引入了接口的私有方法,允许在接口内部定义一些辅助的逻辑或工具方法。在 JDK 10 之前,必须显式声明局部变量类型,导致代码冗长。表达式,可以作为表达式直接返回值,并使用箭头语法,简化了代码。定义多行字符串,自动处理换行符和转义字符,使代码更清晰。语句中显式声明资源,否则无法自动关闭资源。,并且无法直接返回值,代码显得冗长。JDK 9 允许你在。在 JDK 7 中,

而世之奇伟、瑰怪,非常之观,常在于险远,而人之所罕至焉,故非有志者不能至也! 807

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

探秘JDK 13的黑科技:新特性一览

本文深入研究JDK 13的新特性,从改进的Switch表达式到新式的文本块,以及其他引人注目的变化。通过对这些功能的详细解析,读者将对Java编程语言的最新发展趋势有更清晰的认识。

todoitbo的博客 5195

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

JDK13新特性详解

JDK8 新特性详解,2014-03-18正式发布 JDK9 新特性详解,2017-09-21正式发布 JDK10新特性详解,2018-03-20正式发布 JDK11新特性详解,2018-09-25正式发布 JDK12新特性详解,2019-03-19正式发布 JDK13新特性详解,2019-09-17正式发布 ...

骏马逸动,心随你动的博客 537

jdk13新特性

jdk13新特性 转载:https://my.oschina.net/mdxlcj/blog/3107021?from=20190922 转载理由:简洁明了。

Object的博客 1250

dosbox中out of memory_带你了解Java中 JDK8 JDK13 的新特性

某次面试中,面试官问到我这个问题,只勉强说出了 JDK 8 的部分特性,今天就来盘一盘!画外音:JDK 8 就是 JDK 1.8 版本的意思,后续同理。JDK 8 新特性Java 8 (又称为 jdk 1.8) 是 Java 语言开发的一个主要版本。Oracle 公司于 2014 年 3 月 18 日发布 Java 8 ,它支持函数式编程,新的 JavaScript 引擎,新的日期 AP...

weixin_39540725的博客 323

来看看JDK13的81个新特性和API

转载自: Heap Stack Blog - 来看看JDK13你必须知道的81个新特性和API 转载于:https://www.cnblogs.com/alterhu/p/11569270.html

weixin_30613343的博客 412

【Java 进阶】JDK 5 到 13 新特性(JDK 5、6、7、8、9 、10、11、12、13)

文章目录前言一、 JDK 51.自动装箱拆箱2.Foreach其他参考相关 前言 JDK从1.5版本开始,在官方的正式文档与宣传资料中已经不再使用类似JDK1.5的名称,只有程序员内部使用的开发版本号(Developer Version,例如java-version的输出)才继续沿用1.5、1.6、1.7和1.8的版本号,而公开版本号(Product Version)则改为JDK5、JDK6、...

长生的梦呓 765

学Java的同学看过来,JDK13即将发布,新特性会是什么?

首先关注下Tiobe发布的3月份编程语言排行榜,第一名是谁应该完全在意料之中。对,不是C就是Java了。但今天要讲 不是Java,而是与他有着紧密关系的JDK。 JDK是 Java 语言的软件开发工具包,主要用于移动设备、嵌入式设备上的java应用程序。JDK是整个java开发的核心,它包含了JAVA的运行环境(JVM+Java系统类库)和JAVA工具。 目前比较通用的JDK版本是1.8,而JD...

IT知堂 1215
上一篇: JDK 12新特性
下一篇: JDK 14 新特性
优秀小白熊
博客等级 码龄3年 1155粉丝 195原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值