乐趣区

Java13的新特性

Java 语言特性系列

  • Java5 的新特性
  • Java6 的新特性
  • Java7 的新特性
  • Java8 的新特性
  • Java9 的新特性
  • Java10 的新特性
  • Java11 的新特性
  • Java12 的新特性
  • Java13 的新特性
  • Java14 的新特性

本文主要讲述一下 Java13 的新特性

版本号

java -version
openjdk version "13" 2019-09-17
OpenJDK Runtime Environment (build 13+33)
OpenJDK 64-Bit Server VM (build 13+33, mixed mode, sharing)

从 version 信息可以看出是 build 13+33

特性列表

350: Dynamic CDS Archives

JDK5 引入了 Class-Data Sharing 可以用于多个 JVM 共享 class,提升启动速度,最早只支持 system classes 及 serial GC
JDK9 对其进行扩展以支持 application classes 及其他 GC 算法
java10 的新特性 JEP 310: Application Class-Data Sharing 扩展了 JDK5 引入的 Class-Data Sharing,支持 application 的 Class-Data Sharing 并开源出来(以前是 commercial feature)
JDK11 将 -Xshare:off 改为默认 -Xshare:auto,以更加方便使用 CDS 特性
JDK12 的 341: Default CDS Archives 即在 64-bit 平台上编译 jdk 的时候就默认在 ${JAVA_HOME}/lib/server 目录下生成一份名为 classes.jsa 的默认 archive 文件(大概有 18M) 方便大家使用
JDK13 的这个特性支持在 Java application 执行之后进行动态 archive

  • 导出 jsa
java -XX:ArchiveClassesAtExit=hello.jsa -cp hello.jar Hello
  • 使用 jsa
java -XX:SharedArchiveFile=hello.jsa -cp hello.jar Hello

351: ZGC: Uncommit Unused Memory

Java12 的 346: Promptly Return Unused Committed Memory from G1 新增了两个参数分别是 G1PeriodicGCInterval 及 G1PeriodicGCSystemLoadThreshold 用于 GC 之后重新调整 Java heap size,然后将多余的内存归还给操作系统
Java12 的 189: Shenandoah: A Low-Pause-Time Garbage Collector (Experimental) 拥有参数 -XX:ShenandoahUncommitDelay=<milliseconds> 来指定 ZPage 的 page cache 的失效时间,然后归还内存
Java13 则给 ZGC 新增归还 unused heap memory 给操作系统的特性;它新增了几个参数,-XX:ZUncommitDelay=<seconds> 用于指定 ZPage 的 page cache 的失效时间;ZGC 的归还内存默认是开启的,可以使用 -XX:-ZUncommit 来显式禁用

353: Reimplement the Legacy Socket API

本特性替换了 java.net.Socket 以及 java.net.ServerSocket API 的底层实现;它使用 NioSocketImpl 来替换 JDK1.0 的 PlainSocketImpl;如果要继续使用旧版的 Socket 实现,可以使用 -Djdk.net.usePlainSocketImpl 参数来切换到旧版本

/Library/Java/JavaVirtualMachines/jdk-13.jdk/Contents/Home/lib/src.zip!/java.base/java/net/SocketImpl.java

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

354: Switch Expressions (Preview)

本特性主要是使用 yield 替换了 break 来避免歧义,因为 break 可以用来进行跳转执行类似 goto 的操作

    @Test
    public void testSwitchYield(){String dayOfWeek = switch(1){
            case 1 -> {
                String day = "Monday";
                yield day;
            }
            case 2 -> {
                String day = "Tuesday";
                yield day;
            }
            default -> "Unknown";
        };
        System.out.println(dayOfWeek);
    }

355: Text Blocks (Preview)

本特性主要引入了 Text Blocks,使用 ””” 来包围一段 text block,可以内置占位符最后使用 String.format 来填充

    @Test
    public void testTextBlock(){
        // Without Text Blocks
        String html = "<html>\n" +
                "<body>\n" +
                "<p>Hello, Escapes</p>\n" +
                "</body>\n" +
                "</html>\n";
        System.out.println(html);

        // With Text Blocks
        String html2 = """
            <html>
                <body>
                <p>Hello, %s</p>
                </body>
            </html>""";

        System.out.println(String.format(html2, "World"));

        String htmlWithNewLine = """
            <html>
                <body>
                <p>Hello World</p>
                </body>
            </html>
            """;
        System.out.print(htmlWithNewLine);
        System.out.println("a new line");
    }

需要注意 text blocks 不能在一行,另外如果结尾的 ””” 在新的一行则会输出新的一行

细项解读

上面列出的是大方面的特性,除此之外还有一些 api 的更新及废弃,主要见 JDK 13 Release Notes,这里举几个例子。

添加项

  • 添加 FileSystems.newFileSystem(Path, Map<String, ?>) 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 属性处理

jdk.net.URLClassPath.showIgnoredClassPathEntries 属性设置为 true 可以用来帮助查看非法的 Class-Path entries

  • 针对 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 参数的行为

小结

  • Java13 主要新增了如下特性

    • 350: Dynamic CDS Archives
    • 351: ZGC: Uncommit Unused Memory
    • 353: Reimplement the Legacy Socket API
    • 354: Switch Expressions (Preview)
    • 355: Text Blocks (Preview)
  • 语法层面,改进了 Switch Expressions,新增了 Text Blocks,二者皆处于 Preview 状态;API 层面主要使用 NioSocketImpl 来替换 JDK1.0 的 PlainSocketImpl
  • GC 层面则改进了 ZGC,以支持 Uncommit Unused Memory

doc

  • JDK 13 Features
  • JDK 13 Release Notes
  • Oracle JDK 13 Release Notes
  • Java SE deprecated-list
  • The arrival of Java 13!
  • Improve Launch Times On Java 13 With Application Class-Data Sharing
退出移动版