Các tính năng mới của Java 9

1. Khái quát chung

Java 9 đi kèm với một bộ tính năng phong phú. Mặc dù không có khái niệm ngôn ngữ mới, các API và lệnh chẩn đoán mới chắc chắn sẽ rất thú vị đối với các nhà phát triển.

Trong bài viết này, chúng ta sẽ xem xét nhanh, cấp cao về một số tính năng mới; danh sách đầy đủ các tính năng mới có sẵn tại đây.

2. Hệ thống mô-đun - Dự án ghép hình

Hãy bắt đầu với vấn đề lớn - đưa mô-đun vào nền tảng Java.

Hệ thống mô-đun cung cấp các khả năng tương tự như hệ thống của khung công tác OSGi. Mô-đun có khái niệm về sự phụ thuộc, có thể xuất một API công khai và giữ các chi tiết triển khai ẩn / riêng tư.

Một trong những động lực chính ở đây là cung cấp JVM mô-đun, có thể chạy trên các thiết bị có bộ nhớ khả dụng ít hơn rất nhiều. JVM chỉ có thể chạy với những mô-đun và API được ứng dụng yêu cầu. Kiểm tra liên kết này để biết mô tả về các mô-đun này là gì.

Ngoài ra, các API nội bộ (triển khai) của JVM như com.sun. * Không còn có thể truy cập được từ mã ứng dụng.

Nói một cách đơn giản, các mô-đun sẽ được mô tả trong một tệp có tên module-info.java nằm ở đầu cấu trúc phân cấp mã java:

module com.baeldung.java9.modules.car { requires com.baeldung.java9.modules.engines; exports com.baeldung.java9.modules.car.handling; } 

Xe mô-đun của chúng tôi yêu cầu động cơ mô-đun để chạy và xuất một gói để xử lý .

Để biết thêm ví dụ chuyên sâu, hãy kiểm tra OpenJDK Project Jigsaw: Hướng dẫn Bắt đầu Nhanh Hệ thống Mô-đun.

3. Ứng dụng khách HTTP mới

Một sự thay thế đã được chờ đợi từ lâu của HttpURLConnection cũ .

API mới nằm trong gói java.net.http .

Nó phải hỗ trợ cả giao thức HTTP / 2 và bắt tay WebSocket, với hiệu suất tương đương với Apache HttpClient, Netty và Jetty.

Hãy xem chức năng mới này bằng cách tạo và gửi một yêu cầu HTTP đơn giản.

Cập nhật: HTTP Client JEP đang được chuyển sang mô-đun Incubator, vì vậy nó không còn khả dụng trong gói java.net.http nữa và thay vào đó sẽ có sẵn trong jdk.incubator.http.

3.1. Yêu cầu NHẬN nhanh

API sử dụng mẫu Builder, giúp dễ dàng sử dụng nhanh chóng:

HttpRequest request = HttpRequest.newBuilder() .uri(new URI("//postman-echo.com/get")) .GET() .build(); HttpResponse response = HttpClient.newHttpClient() .send(request, HttpResponse.BodyHandler.asString()); 

4. Quy trình API

API quy trình đã được cải tiến để kiểm soát và quản lý các quy trình của hệ điều hành.

4.1. Xử lý thông tin

Lớp java.lang.ProcessHandle chứa hầu hết các chức năng mới:

ProcessHandle self = ProcessHandle.current(); long PID = self.getPid(); ProcessHandle.Info procInfo = self.info(); Optional args = procInfo.arguments(); Optional cmd = procInfo.commandLine(); Optional startTime = procInfo.startInstant(); Optional cpuUsage = procInfo.totalCpuDuration();

Các hiện phương thức trả về một đối tượng đại diện cho một quá trình đang chạy JVM. Lớp con Thông tin cung cấp thông tin chi tiết về quy trình.

4.2. Quy trình phá hủy

Bây giờ - hãy dừng tất cả các tiến trình con đang chạy bằng cách sử dụng hủy () :

childProc = ProcessHandle.current().children(); childProc.forEach(procHandle -> { assertTrue("Could not kill process " + procHandle.getPid(), procHandle.destroy()); });

5. Sửa đổi ngôn ngữ nhỏ

5.1. Thử tài nguyên

Trong Java 7, cú pháp try-with-resources yêu cầu một biến mới được khai báo cho mỗi tài nguyên đang được quản lý bởi câu lệnh.

Trong Java 9 có một cải tiến bổ sung: nếu tài nguyên được tham chiếu bởi biến cuối cùng hoặc biến cuối cùng hiệu quả, thì câu lệnh try-with-resources có thể quản lý tài nguyên mà không cần khai báo biến mới:

MyAutoCloseable mac = new MyAutoCloseable(); try (mac) { // do some stuff with mac } try (new MyAutoCloseable() { }.finalWrapper.finalCloseable) { // do some stuff with finalCloseable } catch (Exception ex) { } 

5.2. Mở rộng nhà khai thác kim cương

Bây giờ chúng ta có thể sử dụng toán tử kim cương kết hợp với các lớp ẩn danh bên trong:

FooClass fc = new FooClass(1) { // anonymous inner class }; FooClass fc0 = new FooClass(1) { // anonymous inner class }; FooClass fc1 = new FooClass(1) { // anonymous inner class }; 

5.3. Giao diện phương pháp riêng tư

Các giao diện trong phiên bản JVM sắp tới có thể có các phương thức riêng tư , có thể được sử dụng để phân chia các phương thức mặc định dài dòng:

interface InterfaceWithPrivateMethods { private static String staticPrivate() { return "static private"; } private String instancePrivate() { return "instance private"; } default void check() { String result = staticPrivate(); InterfaceWithPrivateMethods pvt = new InterfaceWithPrivateMethods() { // anonymous class }; result = pvt.instancePrivate(); } }}

6. Công cụ dòng lệnh JShell

JShell là vòng lặp đọc – eval – in - viết tắt là REPL.

Nói một cách đơn giản, đó là một công cụ tương tác để đánh giá các khai báo, câu lệnh và biểu thức của Java, cùng với một API. Nó rất thuận tiện để kiểm tra các đoạn mã nhỏ, nếu không thì yêu cầu tạo một lớp mới với phương thức chính .

Bản thân tệp thực thi jshell có thể được tìm thấy trong thư mục / bin :

jdk-9\bin>jshell.exe | Welcome to JShell -- Version 9 | For an introduction type: /help intro jshell> "This is my long string. I want a part of it".substring(8,19); $5 ==> "my long string"

Vỏ tương tác đi kèm với lịch sử và tự động hoàn thành; nó cũng cung cấp chức năng như lưu vào và tải từ tệp, tất cả hoặc một số câu lệnh đã viết:

jshell> /save c:\develop\JShell_hello_world.txt jshell> /open c:\develop\JShell_hello_world.txt Hello JShell! 

Các đoạn mã được thực thi khi tải tệp.

7. Lệnh phụ JCMD

Hãy cùng khám phá một số lệnh con mới trong tiện ích dòng lệnh jcmd . Chúng ta sẽ nhận được danh sách tất cả các lớp được tải trong JVM và cấu trúc kế thừa của chúng.

Trong ví dụ dưới đây, chúng ta có thể thấy cấu trúc phân cấp của java.lang.Socket được tải trong JVM đang chạy Eclipse Neon:

jdk-9\bin>jcmd 14056 VM.class_hierarchy -i -s java.net.Socket 14056: java.lang.Object/null |--java.net.Socket/null | implements java.io.Closeable/null (declared intf) | implements java.lang.AutoCloseable/null (inherited intf) | |--org.eclipse.ecf.internal.provider.filetransfer.httpclient4.CloseMonitoringSocket | | implements java.lang.AutoCloseable/null (inherited intf) | | implements java.io.Closeable/null (inherited intf) | |--javax.net.ssl.SSLSocket/null | | implements java.lang.AutoCloseable/null (inherited intf) | | implements java.io.Closeable/null (inherited intf) 

Tham số đầu tiên của lệnh jcmd là id tiến trình (PID) của JVM mà chúng ta muốn chạy lệnh.

Một lệnh con thú vị khác là set_vmflag . Chúng tôi có thể sửa đổi một số tham số JVM trực tuyến mà không cần khởi động lại quy trình JVM và sửa đổi các tham số khởi động của nó.

Bạn có thể tìm ra tất cả các cờ VM có sẵn bằng lệnh con jcmd 14056 VM.flags -all

8. API hình ảnh đa độ phân giải

Giao diện java.awt.image.MultiResolutionImage đóng gói một tập hợp các hình ảnh có độ phân giải khác nhau vào một đối tượng duy nhất. Chúng tôi có thể truy xuất biến thể hình ảnh có độ phân giải cụ thể dựa trên chỉ số DPI nhất định và tập hợp các biến đổi hình ảnh hoặc truy xuất tất cả các biến thể trong hình ảnh.

Lớp java.awt.Graphics được biến thể từ hình ảnh đa độ phân giải dựa trên chỉ số DPI hiển thị hiện tại và bất kỳ biến đổi nào được áp dụng.

Lớp java.awt.image.BaseMultiResolutionImage cung cấp triển khai cơ bản:

BufferedImage[] resolutionVariants = .... MultiResolutionImage bmrImage = new BaseMultiResolutionImage(baseIndex, resolutionVariants); Image testRVImage = bmrImage.getResolutionVariant(16, 16); assertSame("Images should be the same", testRVImage, resolutionVariants[3]); 

9. Tay cầm biến đổi

API nằm trong java.lang.invoke và bao gồm VarHandleMethodHandles . Nó cung cấp các hoạt động tương đương của java.util.concurrent.atomicsun.misc.Unsafe trên các trường đối tượng và phần tử mảng có hiệu suất tương tự.

Với Java 9 Mô-đun hệ thống truy cập vào sun.misc.Unsafe sẽ không thể thực hiện được từ mã ứng dụng.

10. Khung Đăng ký-Xuất bản

Lớp java.util.concurrent.Flow cung cấp các giao diện hỗ trợ khung đăng ký-xuất bản Reactive Streams. Các giao diện này hỗ trợ khả năng tương tác trên một số hệ thống không đồng bộ chạy trên JVM.

Chúng ta có thể sử dụng lớp tiện ích SubmissionPublisher để tạo các thành phần tùy chỉnh.

11. Ghi nhật ký JVM hợp nhất

Tính năng này giới thiệu một hệ thống ghi nhật ký chung cho tất cả các thành phần của JVM. Nó cung cấp cơ sở hạ tầng để thực hiện việc ghi nhật ký, nhưng nó không thêm các lệnh gọi ghi nhật ký thực tế từ tất cả các thành phần JVM. Nó cũng không thêm ghi nhật ký vào mã Java trong JDK.

The logging framework defines a set of tags – for example, gc, compiler, threads, etc. We can use the command line parameter -Xlog to turn on logging during startup.

Let's log messages tagged with ‘gc' tag using ‘debug' level to a file called ‘gc.txt' with no decorations:

java -Xlog:gc=debug:file=gc.txt:none ...

-Xlog:help will output possible options and examples. Logging configuration can be modified runtime using jcmd command. We are going to set GC logs to info and redirect them to a file – gc_logs:

jcmd 9615 VM.log output=gc_logs what=gc

12. New APIs

12.1. Immutable Set

java.util.Set.of() – creates an immutable set of a given elements. In Java 8 creating a Set of several elements would require several lines of code. Now we can do it as simple as:

Set strKeySet = Set.of("key1", "key2", "key3");

The Set returned by this method is JVM internal class: java.util.ImmutableCollections.SetN, which extends public java.util.AbstractSet. It is immutable – if we try to add or remove elements, an UnsupportedOperationException will be thrown.

You can also convert an entire array into a Set with the same method.

12.2. Optional to Stream

java.util.Optional.stream() gives us an easy way to you use the power of Streams on Optional elements:

List filteredList = listOfOptionals.stream() .flatMap(Optional::stream) .collect(Collectors.toList()); 

13. Conclusion

Java 9 sẽ đi kèm với JVM mô-đun và nhiều cải tiến và tính năng mới và đa dạng khác.

Bạn có thể tìm thấy mã nguồn cho các ví dụ trên GitHub.