Tổng quan tính năng mới của Java 12 & 13
Java 12
JDK 12 được phát hành vào ngày 19 tháng 3 năm 2019, đây là một phiên bản không phải LTS.
Bài viết này chọn giới thiệu chi tiết một số tính năng mới quan trọng:
- JEP 189: Shenandoah: A Low-Pause-Time Garbage Collector (Experimental)
- JEP 325: Switch Expressions (Preview) (biểu thức switch, preview feature)
- JEP 334: JVM Constants API (JVM Constants API)
- JEP 344: Abortable Mixed Collections for G1 (mixed collection có thể hủy bỏ của G1)
- JEP 346: Promptly Return Unused Committed Memory (trả lại committed memory chưa sử dụng kịp thời của G1)
Hình dưới đây thể hiện số lượng tính năng mới và thời điểm cập nhật của mỗi phiên bản từ JDK 8 đến JDK 25:

JEP 189: Shenandoah (garbage collector có pause thấp, experimental)
Shenandoah là garbage collector có pause thấp do Red Hat chủ trì phát triển, mục tiêu là vẫn duy trì pause tương đối ngắn và tương đối độc lập với kích thước heap khi heap lớn.
So với ZGC được open source trong Java 11 (cần nâng cấp lên JDK 11 mới có thể sử dụng), Shenandoah có phiên bản JDK8u ổn định. Trong bối cảnh Java 8 đang chiếm thị phần chính, Shenandoah có tính khả thi thực tế cao hơn.
JEP 344 & JEP 346: Tối ưu G1 collector
Java 12 mang đến hai cập nhật cho garbage collector mặc định G1:
- Mixed collection có thể hủy bỏ: JEP 344 tách tập hợp region cần được thu hồi (mixed collection set) thành phần bắt buộc và phần tùy chọn để đạt mục tiêu pause do người dùng cung cấp, nhờ đó G1 garbage collector có thể hủy quá trình garbage collection. G1 có thể hủy việc thu hồi phần tùy chọn để đạt mục tiêu pause.
- Trả lại committed memory chưa sử dụng kịp thời: JEP 346 cải thiện G1 GC để tự động trả memory của Java heap về operating system khi rảnh.
JEP 334: JVM Constants API (JVM Constants API)
JEP này giới thiệu một API để mô hình hóa các mô tả danh nghĩa của các class file và runtime artifact quan trọng, đặc biệt là các constant có thể được load từ constant pool.
API này cung cấp một nhóm interface và utility class để biểu diễn và thao tác với các constant pool entry trong class file. Các thành phần chính gồm:
- Constant descriptor interface: interface
ConstantDescvà các subinterface của nó, dùng để mô tả nhiều loại constant. - Constant value type:
ClassDesc,MethodTypeDesc,MethodHandleDesc,DynamicConstantDesc, v.v. - Bootstrap method: hỗ trợ instruction
invokedynamicvà bootstrap method cho dynamic constant.
API này chủ yếu hỗ trợ các trường hợp sau:
- Thao tác class file: cung cấp cách chuẩn hóa để mô tả và thao tác với constant pool trong class file.
- Sinh bytecode: đơn giản hóa tương tác giữa các framework sinh bytecode (như ASM) và code Java.
- Cải tiến reflection: giúp các thao tác reflection an toàn kiểu hơn và giàu khả năng biểu đạt hơn.
- Công cụ compiler: cung cấp abstraction tốt hơn cho compiler và công cụ sinh code.
API này là một cải tiến tầng dưới quan trọng trong Java 12, đặt nền tảng cho các tính năng thao tác bytecode và compiler về sau.
JEP 325: Switch Expressions (switch expression, preview)
Cú pháp switch truyền thống dễ gặp vấn đề quên viết break; xét về độ gọn gàng của code, nhiều break về bản chất cũng là một dạng lặp lại.
Java 12 cải tiến switch expression, sử dụng execution block với cú pháp tương tự lambda sau khi điều kiện match thành công, không cần viết thêm break.
switch (day) {
case MONDAY, FRIDAY, SUNDAY -> System.out.println(6);
case TUESDAY -> System.out.println(7);
case THURSDAY, SATURDAY -> System.out.println(8);
case WEDNESDAY -> System.out.println(9);
}Java 13
JDK 13 được phát hành vào ngày 17 tháng 9 năm 2019, đây là một phiên bản không phải LTS.
Bài viết này chọn giới thiệu chi tiết một số tính năng mới quan trọng:
- JEP 350: Dynamic CDS Archives (dynamic CDS archive)
- JEP 351: ZGC: Uncommit Unused Memory (ZGC giải phóng memory chưa sử dụng)
- JEP 355: Text Blocks (Preview) (text block, preview feature)
- JEP 354: Switch Expressions (Second Preview) (switch expression, preview lần thứ hai)
Hình dưới đây thể hiện số lượng tính năng mới và thời điểm cập nhật của mỗi phiên bản từ JDK 8 đến JDK 24:

JEP 351: ZGC (giải phóng memory chưa sử dụng)
ZGC được đưa vào Java 11 dưới dạng experimental gặp vấn đề trong thực tế sử dụng: không chủ động giải phóng memory chưa sử dụng cho operating system.
ZGC heap gồm một nhóm heap region có tên là ZPages. Trong GC cycle, khi các region ZPages được làm trống, chúng sẽ được giải phóng và trả về page cache ZPageCache; các ZPages trong cache này được tổ chức theo thứ tự ít được sử dụng gần đây nhất (LRU) và theo kích thước.
Trong Java 13, ZGC sẽ trả về operating system các page được xác định là đã lâu không sử dụng, để chúng có thể được process khác tái sử dụng.
JEP 350: Dynamic CDS Archives (dynamic CDS archive)
Java 13 tiếp tục đơn giản hóa, cải tiến và mở rộng Application Class Data Sharing (AppCDS) được giới thiệu trong Java 10, cụ thể là: cho phép archive class một cách động khi ứng dụng Java kết thúc thực thi. Các class có thể được archive bao gồm mọi application class và class trong các referenced library đã được load nhưng không thuộc default base CDS.
Điều này nâng cao khả năng sử dụng của Application Class Data Sharing (AppCDS). Người dùng không cần chạy thử để tạo class list cho từng ứng dụng.
java -XX:ArchiveClassesAtExit=my_app_cds.jsa -cp my_app.jar
java -XX:SharedArchiveFile=my_app_cds.jsa -cp my_app.jarJEP 355: Text Blocks (text block, preview)
Để giải quyết vấn đề Java chỉ có thể hỗ trợ chuỗi nhiều dòng bằng cách escape newline hoặc dùng toán tử nối dòng, Java 13 giới thiệu ba dấu ngoặc kép liên tiếp để định nghĩa văn bản nhiều dòng.
Java 13 hỗ trợ diễn giải mọi nội dung nằm giữa hai ký hiệu """ thành một phần của string, bao gồm cả newline. Lưu ý: “hai” ở đây nên được hiểu là “một cặp”, tức là một ký hiệu ở đầu và một ký hiệu ở cuối.
Cách viết HTML trước khi hỗ trợ text block:
String json ="{\n" +
" \"name\":\"mkyong\",\n" +
" \"age\":38\n" +
"}\n";Cách viết HTML sau khi hỗ trợ text block:
String json = """
{
"name":"mkyong",
"age":38
}
""";Cách viết SQL trước khi hỗ trợ text block:
String query = "SELECT `EMP_ID`, `LAST_NAME` FROM `EMPLOYEE_TB`\n" +
"WHERE `CITY` = 'INDIANAPOLIS'\n" +
"ORDER BY `EMP_ID`, `LAST_NAME`;\n";Cách viết SQL sau khi hỗ trợ text block:
String query = """
SELECT `EMP_ID`, `LAST_NAME` FROM `EMPLOYEE_TB`
WHERE `CITY` = 'INDIANAPOLIS'
ORDER BY `EMP_ID`, `LAST_NAME`;
""";Giới thiệu các method liên quan đến text block (formatted(), stripIndent(), translateEscapes()), xem phần API enhancement - String enhancement (method liên quan đến text block) trong bài viết này.
JEP 354: Switch Expressions (switch expression, preview lần thứ hai)
Trong switch expression có thêm một keyword dùng để thoát khỏi block switch, đó là yield, chủ yếu dùng để trả về một value.
Điểm khác nhau giữa yield và return: return kết thúc method hiện tại và trả về kết quả, còn yield kết thúc branch của switch expression hiện tại và tạo ra value của expression đó. switch expression phải bao phủ mọi input có thể xảy ra, nhưng khi đã liệt kê hết mọi giá trị thì không nhất thiết cần branch default.
private static String descLanguage(String name) {
return switch (name) {
case "Java": yield "object-oriented, platform independent and secured";
case "Ruby": yield "a programmer's best friend";
default: yield name +" is a good language";
};
}Cải tiến API
Không phải mọi thay đổi API đều được phát hành thông qua JEP (Java Enhancement Proposal).
Trong quy trình phát triển JDK: JEP thường dùng cho các thay đổi lớn, chẳng hạn như giới thiệu language feature mới (như switch expression), cơ chế JVM mới (như ZGC) hoặc refactor library quy mô lớn. Những thay đổi như thêm vài method vào class hiện có, chẳng hạn String.indent(), thường được xem là bảo trì library thông thường. Chúng được developer JDK trực tiếp submit và review thông qua ticket của JBS (JDK Bug System), sau đó được phát hành theo phiên bản.
Cải tiến String
Java 12 bổ sung hai method xử lý string.
indent() - method thụt lề
Method indent() có thể dùng để thụt lề string.
String text = "Java";
// Thụt lề 4 khoảng trắng
text = text.indent(4);
System.out.println(text);
text = text.indent(-10);
System.out.println(text);Output:
Java
Javatransform() - method chuyển đổi
Method transform() có thể dùng để chuyển đổi string được chỉ định.
String result = "foo".transform(input -> input + " bar");
System.out.println(result); // foo barCải tiến Files
Java 12 thêm method mismatch() để so sánh hai file:
public static long mismatch(Path path, Path path2) throws IOExceptionMethod mismatch() dùng để so sánh hai file và trả về vị trí byte đầu tiên không khớp; nếu hai file giống nhau thì trả về -1L.
Ví dụ code (trường hợp nội dung hai file giống nhau):
Path filePath1 = Files.createTempFile("file1", ".txt");
Path filePath2 = Files.createTempFile("file2", ".txt");
Files.writeString(filePath1, "Java 12 Article");
Files.writeString(filePath2, "Java 12 Article");
long mismatch = Files.mismatch(filePath1, filePath2);
assertEquals(-1, mismatch);Ví dụ code (trường hợp nội dung hai file khác nhau):
Path filePath3 = Files.createTempFile("file3", ".txt");
Path filePath4 = Files.createTempFile("file4", ".txt");
Files.writeString(filePath3, "Java 12 Article");
Files.writeString(filePath4, "Java 12 Tutorial");
long mismatch = Files.mismatch(filePath3, filePath4);
assertEquals(8, mismatch);Cải tiến NumberFormat
Trong Java 12, NumberFormat bổ sung hỗ trợ format số theo dạng rút gọn:
NumberFormat fmt = NumberFormat.getCompactNumberInstance(Locale.US, NumberFormat.Style.SHORT);
String result = fmt.format(1000);
System.out.println(result);Output:
1KCải tiến Socket API
Java 13 viết lại tầng dưới của Socket API. NioSocketImpl là phần thay thế trực tiếp cho PlainSocketImpl; nó sử dụng lock trong package java.util.concurrent thay vì synchronized method. Nếu muốn sử dụng implementation cũ, hãy dùng -Djdk.net.usePlainSocketImpl=true.
Ngoài ra, Java 13 mặc định sử dụng Socket implementation mới.
public final class NioSocketImpl extends SocketImpl implements PlatformSocketImpl {
}Cải tiến FileSystems
Trong Java 13, class FileSystems thêm ba method mới dưới đây, giúp sử dụng các file system provider coi nội dung file như một file system dễ dàng hơn:
newFileSystem(Path)newFileSystem(Path, Map<String, ?>)newFileSystem(Path, Map<String, ?>, ClassLoader)
Cải tiến String (method liên quan đến text block)
Java 13 giới thiệu text block dưới dạng preview feature, class String bổ sung 3 method để thao tác với text block:
formatted(Object... args): tương tự methodformat()củaString. Method này được thêm để hỗ trợ format text block.stripIndent(): dùng để loại bỏ khoảng trắng ở đầu và cuối mỗi dòng trong text block.translateEscapes(): chuyển escape sequence như "\\t" thành "\t".
Vì text block là một preview feature và có thể bị xóa trong các phiên bản tương lai, các method mới này được đánh dấu là deprecated.
@Deprecated(forRemoval=true, since="13")
public String stripIndent() {
}
@Deprecated(forRemoval=true, since="13")
public String formatted(Object... args) {
}
@Deprecated(forRemoval=true, since="13")
public String translateEscapes() {
}Để xem giới thiệu chi tiết về text block, hãy xem phần JEP 355: Text Blocks (Preview) trong bài viết này.
Bổ sung
Về preview feature
Trước tiên, hãy trích nguyên văn từ website Oracle: This is a preview feature, which is a feature whose design, specification, and implementation are complete, but is not permanent, which means that the feature may exist in a different form or not at all in future JDK releases. To compile and run code that contains preview features, you must specify additional command-line options.
Đây là một preview feature có thiết kế, đặc tả và implementation hoàn chỉnh nhưng không mang tính vĩnh viễn. Điều đó có nghĩa là feature này có thể tồn tại dưới hình thức khác hoặc hoàn toàn không tồn tại trong các bản phát hành JDK tương lai. Để compile và run code chứa preview feature, phải chỉ định thêm các command-line option.
Lấy switch expression làm ví dụ: feature này bắt đầu preview từ Java 12, tiếp tục được điều chỉnh trong Java 13 và trở thành language feature chính thức trong Java 14. Sau khi chính thức hóa, syntax và semantics của nó trở thành một phần của Java SE specification, không còn cần bật preview feature.
Một mặt, có thể thấy JDK, với tư cách là platform tiêu chuẩn, rất thận trọng khi bổ sung feature mới. Mặt khác, theo quan điểm cá nhân, nên thận trọng khi sử dụng preview feature. Thiết kế và implementation của feature có thể dễ dàng, nhưng giá trị thực tế vẫn cần được kiểm chứng trong quá trình sử dụng.
Tối ưu JVM
Mỗi lần phát hành phiên bản Java đều đi kèm tối ưu cho JVM, bao gồm cải tiến garbage collection algorithm hiện có, giới thiệu garbage collection algorithm mới và loại bỏ các garbage collection algorithm cũ không còn phù hợp.
Hướng tối ưu tổng thể là hiệu năng garbage collection cao, độ trễ thấp.
Các developer ứng dụng thường quan tâm hơn đến syntax feature mới, nhưng từ góc độ doanh nghiệp, khi cân nhắc nâng cấp Java platform, điều được quan tâm hơn là cải thiện runtime của JVM.
Tham khảo
- JDK Project Overview: https://openjdk.java.net/projects/jdk/
- Oracle Java12 ReleaseNote: https://www.oracle.com/java/technologies/javase/12all-relnotes.htm
- What is new in Java 12: https://mkyong.com/java/what-is-new-in-java-12/
- Oracle Java13 ReleaseNote https://www.oracle.com/technetwork/java/javase/13all-relnotes-5461743.html#NewFeature
- New Java13 Features https://www.baeldung.com/java-13-new-features
- Tổng quan tính năng mới của Java 13 https://www.ibm.com/developerworks/cn/java/the-new-features-of-Java-13/index.html
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.
