Tổng quan các tính năng mới của Java 19
JDK 19 được phát hành chính thức vào ngày 20 tháng 9 năm 2022, không phải là phiên bản hỗ trợ dài hạn.
JDK 19 có tổng cộng 7 tính năng mới. Bài viết này sẽ chọn một số tính năng mới quan trọng để giới thiệu chi tiết:
- JEP 424: Foreign Function & Memory API (API hàm và bộ nhớ bên ngoài) (preview)
- JEP 425: Virtual Threads (virtual thread) (preview)
- JEP 426: Vector API (incubator lần thứ tư)
- JEP 428: Structured Concurrency (incubator)
Hình dưới đây thể hiện số lượng tính năng mới và thời gian cập nhật do mỗi phiên bản từ JDK 8 đến JDK 25 mang lại:

JEP 424: Foreign Function & Memory API (preview)
Chương trình Java có thể sử dụng API này để tương tác với code và dữ liệu bên ngoài Java runtime. Bằng cách gọi hiệu quả external function (tức code bên ngoài JVM) và truy cập an toàn external memory (tức memory không do JVM quản lý), API này cho phép chương trình Java gọi native library và xử lý native data mà không gặp các rủi ro và tính mong manh như JNI.
Foreign Function & Memory API trải qua vòng incubator đầu tiên trong Java 17, do JEP 412 đề xuất. Vòng incubator thứ hai do JEP 419 đề xuất và được tích hợp vào Java 18; bản preview do JEP 424 đề xuất và được tích hợp vào Java 19.
Trước khi có Foreign Function & Memory API:
- Java cung cấp một số method thực hiện các thao tác cấp thấp, không an toàn thông qua
sun.misc.Unsafe, chẳng hạn truy cập trực tiếp vào system memory resource và tự quản lý memory resource. ClassUnsafecho Java khả năng thao tác trên memory space tương tự pointer của C, nhưng cũng làm tăng tính không an toàn của Java; sử dụng classUnsafekhông đúng sẽ làm tăng khả năng chương trình gặp lỗi. - Java đã hỗ trợ gọi native method thông qua Java Native Interface (JNI) từ Java 1.1, nhưng JNI không dễ sử dụng. Việc triển khai JNI quá phức tạp, nhiều bước (có thể tham khảo các bước cụ thể trong bài viết này: Guide to JNI (Java Native Interface)), không chịu sự kiểm soát của cơ chế bảo đảm an toàn ngôn ngữ của JVM và ảnh hưởng đến tính cross-platform của Java. Ngoài ra, performance của JNI cũng không tốt vì JNI method call không thể hưởng lợi từ nhiều JIT optimization phổ biến, như inline. Mặc dù các framework như JNA, JNR và JavaCPP đã cải tiến JNI, hiệu quả vẫn chưa thật sự lý tưởng.
Foreign Function & Memory API được giới thiệu để giải quyết một số vấn đề khi Java truy cập external function và external memory.
Foreign Function & Memory API (FFM API) định nghĩa các class và interface:
- Phân bổ external memory:
MemorySegment,MemoryAddressvàSegmentAllocator - Thao tác và truy cập external memory có cấu trúc:
MemoryLayout,VarHandle - Kiểm soát việc phân bổ và giải phóng external memory:
MemorySession - Gọi external function:
Linker,FunctionDescriptorvàSymbolLookup
Dưới đây là ví dụ sử dụng FFM API. Đoạn code này lấy method handle của function radixsort trong C library, sau đó dùng nó để sắp xếp bốn string trong mảng Java.
// 1. Tìm external function trong path của C library
Linker linker = Linker.nativeLinker();
SymbolLookup stdlib = linker.defaultLookup();
MethodHandle radixSort = linker.downcallHandle(
stdlib.lookup("radixsort"), ...);
// 2. Phân bổ memory trên heap để lưu bốn string
String[] javaStrings = { "mouse", "cat", "dog", "car" };
// 3. Phân bổ off-heap memory để lưu bốn pointer
SegmentAllocator allocator = implicitAllocator();
MemorySegment offHeap = allocator.allocateArray(ValueLayout.ADDRESS, javaStrings.length);
// 4. Sao chép string từ heap sang off-heap memory
for (int i = 0; i < javaStrings.length; i++) {
// Phân bổ một string trong off-heap memory, sau đó lưu pointer trỏ đến nó
MemorySegment cString = allocator.allocateUtf8String(javaStrings[i]);
offHeap.setAtIndex(ValueLayout.ADDRESS, i, cString);
}
// 5. Sắp xếp dữ liệu trong off-heap memory bằng cách gọi external function
radixSort.invoke(offHeap, javaStrings.length, MemoryAddress.NULL, '\0');
// 6. Sao chép string (đã được sắp xếp lại) từ off-heap memory về heap
for (int i = 0; i < javaStrings.length; i++) {
MemoryAddress cStringPtr = offHeap.getAtIndex(ValueLayout.ADDRESS, i);
javaStrings[i] = cStringPtr.getUtf8String(0);
}
assert Arrays.equals(javaStrings, new String[] {"car", "cat", "dog", "mouse"}); // trueJEP 425: Virtual Threads (preview)
Virtual thread là thread nhẹ do JDK chứ không phải OS triển khai. Nhiều virtual thread chia sẻ cùng một OS thread, vì vậy số lượng virtual thread có thể lớn hơn rất nhiều số lượng OS thread.
Virtual thread đã được chứng minh là rất hữu ích trong các ngôn ngữ multithreading khác, chẳng hạn như Goroutine trong Go và process trong Erlang.
Virtual thread thường không cần tạo hoặc chuyển đổi một OS thread cho mỗi task, nhờ đó giảm resource của thread và scheduling overhead do một lượng lớn blocking task gây ra, đồng thời giảm công sức viết, duy trì và quan sát các concurrent application có throughput cao.
Zhihu có một cuộc thảo luận về virtual thread của Java 19, nếu quan tâm bạn có thể xem: https://www.zhihu.com/question/536743167.
Có thể xem phần giải thích chi tiết và nguyên lý của Java virtual thread trong các bài viết dưới đây:
- Nguyên lý và phân tích performance của virtual thread|DeWu Technology
- Java 19 chính thức GA! Xem virtual thread cải thiện đáng kể throughput của system như thế nào
- Virtual thread - Phân tích source code VirtualThread
JEP 426: Vector API (incubator lần thứ tư)
Vector API ban đầu do JEP 338 đề xuất và được tích hợp vào Java 16 dưới dạng incubator API. Vòng incubator thứ hai do JEP 414 đề xuất và được tích hợp vào Java 17; vòng incubator thứ ba do JEP 417 đề xuất và được tích hợp vào Java 18; vòng thứ tư do JEP 426 đề xuất và được tích hợp vào Java 19.
Trong Tổng quan các tính năng mới của Java 18, tôi đã giới thiệu chi tiết về Vector API, nên ở đây không giới thiệu thêm.
JEP 428: Structured Concurrency (incubator)
JDK 19 giới thiệu Structured Concurrency, một phương pháp lập trình multithreading nhằm đơn giản hóa việc lập trình nhiều thread thông qua Structured Concurrency API, không nhằm thay thế java.util.concurrent và hiện đang ở giai đoạn incubator.
Structured Concurrency xem nhiều task chạy trong các thread khác nhau như một work unit duy nhất, qua đó đơn giản hóa việc xử lý lỗi, nâng cao reliability và tăng observability. Nói cách khác, Structured Concurrency giữ lại readability, maintainability và observability của code single-thread.
API cơ bản của Structured Concurrency là StructuredTaskScope. StructuredTaskScope hỗ trợ chia task thành nhiều concurrent subtask, thực thi chúng trong thread riêng và yêu cầu subtask phải hoàn thành trước khi main task tiếp tục.
Cách sử dụng cơ bản của StructuredTaskScope như sau:
try (var scope = new StructuredTaskScope<Object>()) {
// Dùng method fork để tạo thread thực thi subtask
Future<Integer> future1 = scope.fork(task1);
Future<String> future2 = scope.fork(task2);
// Chờ thread hoàn thành
scope.join();
// Xử lý result có thể bao gồm xử lý exception hoặc rethrow exception
... process results/exceptions ...
} // closeStructured Concurrency rất phù hợp với virtual thread, một loại thread nhẹ do JDK triển khai. Nhiều virtual thread chia sẻ cùng một OS thread, nhờ đó cho phép có rất nhiều virtual thread.
Lời cuối
Nếu nội dung hữu ích với bạn, hãy tiện tay tặng JavaGuide một Star miễn phí để ủng hộ: GitHub | Gitee.
JavaGuide đã được duy trì gần bảy năm, tích lũy 6100+ commit, với sự chung tay hoàn thiện của 620+ contributor. Star, phản hồi và PR của bạn đều là động lực để dự án tiếp tục cập nhật.
Nếu bạn đang chuẩn bị phỏng vấn backend / phát triển ứng dụng AI, có thể tham khảo Knowledge Planet của tôi, bao gồm các project thực tế về backend và AI, tối ưu CV, hỏi đáp 1-1 và tài liệu về các trọng điểm thường gặp, đã được duy trì liên tục sáu năm.
