Bỏ qua tới nội dung chính
Development

JDK 27 đã chính thức được phát hành với những cải tiến vô cùng mạnh mẽ

Phạm Đăng Sa 16 phút đọc
JDK 27 đã chính thức được phát hành với những cải tiến vô cùng mạnh mẽ

Mỗi phiên bản Java mới đều cần được đánh giá về mức độ cần thiết khi nâng cấp. Nhiều phiên bản giới thiệu các tính năng preview hấp dẫn nhưng chưa được áp dụng ngay trong môi trường production.

Ngày 15/9/2026, Oracle chính thức phát hành JDK 27, bản triển khai tham chiếu của Java SE 27, tương ứng với JSR 402.


Mỗi phiên bản Java mới đều cần được đánh giá về mức độ cần thiết khi nâng cấp. Nhiều phiên bản giới thiệu các tính năng preview hấp dẫn nhưng chưa được áp dụng ngay trong môi trường production.


JDK 27 có 9 JEP độc lập, gồm 4 tính năng preview và 1 tính năng incubator.


Đáng chú ý, một số thay đổi tác động đến hành vi mặc định của JVM, giúp ứng dụng hưởng lợi ngay sau khi nâng cấp mà không cần sửa mã nguồn.


Dưới đây là các thay đổi quan trọng.

Có gì thay đổi trong JDK 27?

Dưới đây là tổng quan nhanh các thay đổi:

JEP

Tính năng

Trạng thái

Tác động chính

JEP 523

G1 trở thành bộ thu gom rác (GC) mặc định cho mọi môi trường

Chính thức (Final)

Hành vi GC nhất quán hơn

JEP 534

Compact Object Headers trở thành mặc định

Chính thức (Final)

Giảm kích thước header của đối tượng và mức sử dụng bộ nhớ

JEP 527

Trao đổi khóa lai kháng lượng tử cho TLS 1.3

Chính thức (Final)

Tăng cường bảo mật hậu lượng tử

JEP 531

Lazy Constants (Hằng số khởi tạo lười)

Xem trước (Preview)

Khởi tạo lười với tối ưu hóa dành cho các giá trị dạng hằng số

JEP 532

Primitive Type Pattern Matching

Xem trước (Preview)

Hỗ trợ so khớp mẫu với các kiểu dữ liệu nguyên thủy

JEP 533

Structured Concurrency (Lập trình đồng thời có cấu trúc)

Xem trước (Preview)

Lập trình đồng thời an toàn và đơn giản hơn

JEP 537

Vector API

Thử nghiệm (Incubator)

Tăng tốc SIMD cho AI và các tác vụ khoa học

JEP 536

JFR In-Process Data Anonymization (Ẩn danh dữ liệu trong tiến trình JFR)

Chính thức (Final)

Chẩn đoán production an toàn hơn

JEP 538

PEM Encoding API

Xem trước (Preview)

Chuẩn hóa cách mã hóa khóa và chứng chỉ

Điều thú vị nhất là một vài thay đổi trong số này không chỉ đơn thuần là các API hay cú pháp mới.

 

Chúng làm thay đổi cách thức hoạt động mặc định của JVM.

 

1. G1 trở thành GC mặc định trong mọi môi trường

Đây là một trong những thay đổi lớn nhất của JDK 27.


Từ JDK 9, G1 là GC mặc định trong môi trường server. Tuy nhiên, ở môi trường hạn chế bộ nhớ như container nhỏ hoặc ứng dụng CLI đơn giản, JVM có thể chọn Serial GC.


Serial GC chỉ sử dụng một luồng, nên Full GC có thể gây ra thời gian tạm dừng dài. Với dữ liệu nhỏ, độ trễ này có thể không đáng kể, nhưng khi khối lượng dữ liệu tăng, thời gian tạm dừng có thể trở nên khó chấp nhận.


JEP 523 trong JDK 27 thay đổi điều này: G1 trở thành GC mặc định cho mọi môi trường, không còn phân biệt server và môi trường bị giới hạn tài nguyên.

Vì sao có thể chuyển sang G1?

Theo JEP, sau nhiều năm tối ưu liên tục, G1 đã đạt hiệu năng tương đương Serial GC trên mọi chỉ số.

Cụ thể:

  • Throughput: JDK 27 giảm chi phí đồng bộ hóa của G1 (JEP 522), giúp throughput tối đa gần bằng Serial GC.

  • Latency: G1 thu gom rác thế hệ cũ theo từng phần (incremental garbage collection), thay vì thu gom toàn bộ như Serial GC, nên độ trễ tối đa thấp hơn.

  • Native Memory: Các phiên bản gần đây đã giảm mức sử dụng native memory của G1 xuống tương đương Serial GC.

  • Startup Time: Với heap nhỏ, chi phí khởi động của G1 đã được tối ưu đến mức gần như không đáng kể.

Có cần thay đổi code không?

Không cần thay đổi gì.

Khi nâng cấp lên JDK 27 mà không chỉ định GC cụ thể, JVM sẽ tự động sử dụng G1.

Nếu trước đây bạn gặp tình trạng tạm dừng lâu do Full GC khi dùng Serial GC trong môi trường ít bộ nhớ, vấn đề này sẽ được khắc phục khi nâng cấp lên JDK 27.

Nếu có lý do cụ thể để tiếp tục dùng Serial GC, bạn vẫn có thể cấu hình thủ công:

-XX:+UseSerialGC

 

Tuy nhiên, G1 là lựa chọn mặc định phù hợp hơn.

2. Compact Object Headers trở thành mặc định

Đây là một thay đổi diễn ra âm thầm: object header giảm từ 96 bit xuống 64 bit.

Đây cũng là thay đổi về hành vi mặc định. Bạn không cần sửa mã nguồn, chỉ cần nâng cấp JDK để áp dụng.

Trên JVM 64-bit, cấu trúc object header truyền thống gồm:

  • Mark Word: 64 bit, lưu hash code, tuổi của đối tượng trong GC, trạng thái khóa, v.v.

  • Klass Pointer: 64 bit, trỏ đến metadata của lớp (sau đó có thể được nén xuống 4 byte).

Tổng cộng, object header chiếm 96 bit (12 byte).

Ví dụ, với lệnh:

new Object();

 

Trên JVM 64-bit, đối tượng đơn giản này thực tế chiếm 16 byte, bao gồm 12 byte object header và 4 byte đệm căn chỉnh (alignment padding).

 

JEP 534 thay đổi điều gì?

JEP 534 nén Klass Pointer từ 64 bit xuống 32 bit, giúp object header giảm còn 64 bit (8 byte).


Lý do: vùng bộ nhớ chứa metadata của layer trong JVM thường không vượt quá 4 GB, nên không cần địa chỉ 64 bit đầy đủ. Klass Pointer chỉ cần lưu index để tham chiếu đến metadata.


Kết quả: new Object() giảm từ 16 byte xuống 12 byte (8 byte object header + 4 byte alignment padding). Mức sử dụng heap giảm 25% đối với object đơn giản này.

Tại sao thay đổi này quan trọng?

Giảm 25% mức sử dụng heap mang lại những lợi ích tiềm năng:

  • Lưu trữ được nhiều object hơn với cùng dung lượng bộ nhớ.

  • Giảm áp lực lên GC, do khối lượng dữ liệu cần quét và thu hồi giảm.

  • Cải thiện data locality nhờ các object gọn hơn, có thể tăng tỷ lệ cache hit của CPU.

  • Cải thiện hiệu quả sử dụng CPU cache.

Với các ứng dụng Java quy mô lớn, đặc biệt là những ứng dụng tạo nhiều object nhỏ, đây có thể là một cải thiện hiệu năng đáng kể.


Compact Object Headers đã là tính năng tùy chọn từ JDK 24. Sau hai phiên bản kiểm chứng, JDK 27 chính thức đặt tính năng này làm mặc định.


Tương tự G1, bạn không cần thao tác thêm; thay đổi có hiệu lực ngay khi nâng cấp JDK.

3. Trao đổi Post-Quantum Hybrid Key cho TLS 1.3

Thay đổi này tập trung vào bảo mật, hướng đến khả năng chống lại các mối đe dọa từ máy tính lượng tử trong tương lai.


Hệ thống mật mã có vòng đời dài. Dữ liệu mã hóa bị thu thập hôm nay có thể được lưu trữ và giải mã trong tương lai khi máy tính lượng tử đủ mạnh xuất hiện. Rủi ro này thường được gọi là “Store now, crack later” — thu thập dữ liệu trước, giải mã sau.


JDK 27 bổ sung thuật toán post-quantum hybrid key cho TLS 1.3. Cơ chế lai kết hợp thuật toán kháng lượng tử (quantum-resistant) với thuật toán truyền thống, giúp kết nối vẫn được bảo vệ nếu thuật toán truyền thống bị phá vỡ.


Các thuật toán mới gồm:

  • X25519MLKEM768 — được ưu tiên cao nhất trong danh sách mặc định.

  • SecP256r1MLKEM768

  • SecP384r1MLKEM1024

Nếu sử dụng API javax.net.ssl, các thuật toán này sẽ được áp dụng theo cấu hình mặc định sau khi nâng cấp lên JDK 27, không cần sửa mã nguồn.


Nhờ đó, các kết nối HTTPS hiện có có thể tự động sử dụng cơ chế trao đổi post-quantum hybrid key mà không cần thay đổi ứng dụng.

4. Lazy Constants: Hữu ích cho ứng dụng AI và xử lý dữ liệu lớn

JEP 531 giới thiệu Lazy Constants ở lần preview thứ ba.


Vấn đề cần giải quyết là việc khởi tạo dữ liệu tốn kém ngay khi lớp được khởi tạo, ngay cả khi dữ liệu chưa cần sử dụng.


Ví dụ:

private static final LazyConstant<List<Config>> CONFIGS =

LazyConstant.of(() -> loadFromDatabase());

 

Nếu loadFromDatabase() tốn nhiều thời gian, ứng dụng vẫn phải chịu chi phí này dù chưa cần đến dữ liệu.

Lazy Constants cho phép trì hoãn việc khởi tạo, đồng thời giúp JVM vẫn có thể xem giá trị sau khi khởi tạo là hằng số để tối ưu hóa.

Ví dụ về mặt ý tưởng:

private static final LazyConstant<List<Config>> CONFIGS =

LazyConstant.of(() -> loadFromDatabase());

 

Sau đó, truy cập giá trị khi cần:

 

public List getConfigs() {

return CONFIGS.get();

}

Nhờ vậy, quá trình khởi tạo tốn kém chỉ diễn ra khi giá trị thực sự được sử dụng.

Vì sao tính năng này hữu ích cho AI?

Các ứng dụng AI hiện đại thường sử dụng những tài nguyên chỉ đọc nhưng tốn nhiều chi phí để tải, chẳng hạn:

  • Trọng số mô hình (model weights)

  • Từ vựng của tokenizer

  • Chỉ mục vector (vector indexes)

  • Cấu trúc cấu hình lớn

Tải tất cả tài nguyên ngay khi ứng dụng khởi động có thể làm tăng thời gian khởi động và áp lực bộ nhớ.


Vì vậy, lazy initialization đặc biệt hữu ích khi các tài nguyên này chưa cần được sử dụng ngay.


Lưu ý: tính năng vẫn đang ở giai đoạn preview, nên cần đánh giá kỹ trước khi áp dụng vào môi trường production.

5. Pattern Matching cho kiểu dữ liệu nguyên thủy

JEP 532 mở rộng pattern matching cho các kiểu dữ liệu nguyên thủy (primitive types) như int.


Trước đây, pattern matching chủ yếu hỗ trợ các kiểu tham chiếu (reference types), chẳng hạn:

  • String

  • Enum

  • Các lớp wrapper

  • Những đối tượng khác

Với JDK 27, tính năng preview này cho phép sử dụng kiểu nguyên thủy trong các cấu trúc như switch và instanceof.

Đây là lần preview thứ năm của tính năng này, đưa Java tiến gần hơn đến phiên bản chính thức.

Ví dụ:

 

Object obj = getStatusCode();

 

return switch (obj) {

case int i when i == 200 -> "OK";

case int i when i == 404 -> "Not Found";

case String s -> "String: " + s;

default -> "Unknown";

};

Điều này giúp pattern matching linh hoạt hơn và nhất quán hơn giữa kiểu nguyên thủy và kiểu tham chiếu.


JEP cũng tăng cường kiểm tra switch dominance, giúp trình biên dịch phát hiện sớm thêm các trường hợp có vấn đề.

6. Structured Concurrency (Lập trình đồng thời có cấu trúc)

JEP 533 giới thiệu lần preview thứ bảy của Structured Concurrency. Dù vẫn đang ở giai đoạn preview, đây là tính năng đáng chú ý đối với các nhà phát triển Java có ứng dụng xử lý đồng thời.

Với cách lập trình truyền thống, các tác vụ đồng thời dễ gặp vấn đề về quản lý vòng đời (lifecycle):

Ví dụ:

Future userFuture =

executor.submit(() -> fetchUser(id));

 

Future orderFuture =

executor.submit(() -> fetchOrder(id));

 

try {

User user = userFuture.get();

Order order = orderFuture.get();

return new Result(user, order);

} catch (Exception e) {

throw e;

}

 

Vấn đề là life circle của hai tác vụ này không gắn với tác vụ cha.


Nếu tác vụ cha thất bại, tác vụ con vẫn có thể tiếp tục chạy. Nếu một tác vụ con thất bại, tác vụ cha có thể không biết cách hủy tác vụ còn lại.


Cụ thể:

  • Điều gì xảy ra nếu fetchUser() thất bại?

  • fetchOrder() nên tiếp tục chạy hay bị hủy?

  • Nếu tác vụ cha kết thúc khi tác vụ con vẫn đang chạy thì sao?

Vấn đề cốt lõi là vòng đời của các tác vụ không được liên kết với nhau một cách tự động.

Structured Concurrency thay đổi cách tiếp cận

Với Structured Concurrency:

try (var scope =

new StructuredTaskScope.ShutdownOnFailure()) {

 

Supplier user =

scope.fork(() -> fetchUser(id));

 

Supplier order =

scope.fork(() -> fetchOrder(id));

 

scope.join();

 

scope.throwIfFailed();

 

return new Result(user.get(), order.get());

}

 

Các tác vụ con được quản lý trong phạm vi (scope) của tác vụ cha.

  • Nếu một tác vụ thất bại, scope có thể yêu cầu các tác vụ còn lại dừng lại.

  • Khi scope kết thúc, các tác vụ con chưa hoàn thành được xử lý tự động theo chính sách của scope.

Điểm cốt lõi không chỉ là cú pháp mới, mà là quản lý vòng đời tác vụ.

Structured Concurrency giúp xác định rõ mối quan hệ giữa tác vụ cha và các tác vụ con.

7. Vector API: Java tiến gần hơn đến khả năng vector hóa ở hardware level

AI và điện toán khoa học thường sử dụng các phép toán vector. CPU ngày càng hỗ trợ nhiều lệnh SIMD, cho phép một lệnh xử lý nhiều phần tử dữ liệu cùng lúc.


Vector API giúp ứng dụng Java khai thác các khả năng này. JDK 27 tiếp tục phát triển API ở giai đoạn incubator, lần thứ 12.


Ví dụ cộng vector đơn giản:

FloatVector a =

FloatVector.fromArray(SPECIES, arr1, i);

 

FloatVector b =

FloatVector.fromArray(SPECIES, arr2, i);

 

FloatVector c = a.add(b);

 

c.intoArray(result, i);

 

Thay vì xử lý từng giá trị riêng lẻ, các lệnh vector có thể xử lý nhiều giá trị cùng lúc.

API này hữu ích cho các tác vụ như:

  • Tính toán số học

  • Tính độ tương đồng vector

  • Phép toán ma trận

  • Suy luận AI (AI inference)

  • Mô phỏng khoa học

Nếu ứng dụng AI chạy trên CPU hỗ trợ AVX-512 hoặc ARM SVE, Vector API cho phép mã Java khai thác trực tiếp khả năng tính toán vector của phần cứng.


Lưu ý: Vector API vẫn đang ở giai đoạn incubator, chưa phải tính năng chính thức.

8. Ẩn danh dữ liệu ngay trong tiến trình JFR

Phân tích hiệu năng trong môi trường production có thể vô tình làm lộ thông tin nhạy cảm.


Java Flight Recorder (JFR) có thể ghi lại các thông tin khi chạy, chẳng hạn:

  • Tham số dòng lệnh

  • Biến môi trường

  • Thuộc tính hệ thống

JDK 27 bổ sung tính năng ẩn danh dữ liệu ngay trong tiến trình JFR, cho phép ẩn danh thông tin nhạy cảm trước khi dữ liệu rời khỏi tiến trình.


Điều này giúp hạn chế nguy cơ rò rỉ thông tin xác thực (credentials) hoặc cấu hình nhạy cảm khi thu thập dữ liệu chẩn đoán trong production.

9. Các cải tiến đáng chú ý khác

JDK 27 còn bổ sung một số cải tiến khác:

JSON Thread Dumps

Các thông tin như ID luồng, số lượng luồng và ID tiến trình được biểu diễn dưới dạng JSON number, giúp các công cụ giám sát và tự động hóa xử lý dữ liệu dễ dàng hơn.

jcmd VM.security_properties

Bổ sung lệnh cho phép kiểm tra các thuộc tính bảo mật tại thời điểm chạy (runtime).

Post-Quantum Key Encoding

Cập nhật cơ chế mã hóa khóa riêng cho ML-KEM và ML-DSA, đồng thời cải thiện hiệu năng của X25519 và Ed25519.

Loại bỏ JVMCI

Một số chức năng và tùy chọn JVMCI cũ đã bị loại bỏ. Điều này đặc biệt đáng lưu ý nếu môi trường của bạn phụ thuộc vào các công nghệ được xây dựng dựa trên JVMCI.

Những lợi ích lớn nhất của JDK 27

JDK 27 mang lại một số cải tiến chính:

1. Cải thiện hành vi mặc định của JVM

G1 trở thành GC mặc định trong mọi môi trường. Ứng dụng không cần thiết kế lại để hưởng lợi.

2. Giảm mức sử dụng bộ nhớ

Compact Object Headers giảm kích thước object header, giúp tiết kiệm đáng kể bộ nhớ với ứng dụng có nhiều đối tượng nhỏ.

3. Tăng cường bảo mật mật mã

Cơ chế trao đổi khóa lai hậu lượng tử bổ sung khả năng bảo vệ kháng lượng tử cho TLS 1.3.

4. Cải thiện xử lý đồng thời

Structured Concurrency cung cấp mô hình rõ ràng hơn để quản lý các tác vụ đồng thời liên quan và vòng đời của chúng.

5. Hỗ trợ tốt hơn cho AI và xử lý dữ liệu

Lazy Constants và Vector API hữu ích với các ứng dụng cần khởi tạo tài nguyên tốn kém hoặc thực hiện nhiều phép tính số học.

6. Chẩn đoán production an toàn hơn

Tính năng ẩn danh dữ liệu JFR giúp giảm nguy cơ lộ thông tin nhạy cảm khi phân tích hiệu năng.

Những điều cần cân nhắc trước khi nâng cấp

JDK 27 không phải bản LTS, điều này rất quan trọng.

Theo bài viết, JDK 25 là bản LTS được khuyến nghị cho môi trường production cần tính ổn định lâu dài, trong khi JDK 27 có thời gian hỗ trợ ngắn hơn.

Ngoài ra, cần lưu ý một số điểm sau.

Tính năng Preview và Incubator

Các tính năng như: Lazy Constants, Primitive Type Pattern Matching, Structured Concurrency, Vector API yêu cầu cơ chế Preview/Incubator và có thể thay đổi trong các phiên bản tương lai.

Để sử dụng tính năng Preview, cần thêm tùy chọn:

--enable-preview

 

Khả năng tương thích với JVMCI

Nếu ứng dụng hoặc môi trường chạy phụ thuộc vào JVMCI hay cấu hình JIT dựa trên Graal, việc loại bỏ JVMCI đòi hỏi phải kiểm tra kỹ khả năng tương thích.

Khả năng tương thích của công cụ

Compact Object Headers có thể yêu cầu cập nhật một số công cụ chẩn đoán và profiling phụ thuộc vào cấu trúc object header.

JDK 27 phù hợp trong những trường hợp nào?

Mỗi môi trường khác nhau đều có những yếu tố cần cân nhắc riêng.

Tình huống

Điều cần cân nhắc

Học tập / Dự án cá nhân

Phù hợp để tìm hiểu và thử nghiệm JDK 27

Container có bộ nhớ hạn chế

G1 và Compact Object Headers đặc biệt hữu ích

Ứng dụng Java quy mô lớn

Có thể tiết kiệm bộ nhớ, nhưng cần đánh giá rủi ro khi dùng bản không phải LTS

Ứng dụng HTTPS yêu cầu bảo mật cao

Các khả năng TLS hậu lượng tử rất đáng quan tâm

Ứng dụng AI / Dữ liệu

Nên thử nghiệm Lazy Constants và Vector API

Hệ thống production dài hạn

Cân nhắc chiến lược sử dụng các bản LTS

Hệ thống phụ thuộc Graal/JVMCI

Kiểm tra khả năng tương thích trước khi chuyển đổi

 

Vậy có nên nâng cấp lên JDK 27 không?

Điểm đáng chú ý nhất của JDK 27 không phải là cú pháp Java mới, mà là nhiều cải tiến không yêu cầu thay đổi mã nguồn ứng dụng.

Ba thay đổi nổi bật:

G1 trở thành GC mặc định

JVM hướng tới chiến lược thu gom rác nhất quán hơn giữa các môi trường.

Compact Object Headers trở thành mặc định

Các object có thể sử dụng ít bộ nhớ hơn, đặc biệt hữu ích với ứng dụng có nhiều object.

Post-Quantum TLS được bật mặc định

Các ứng dụng hiện có có thể sử dụng cơ chế bảo vệ mật mã mạnh hơn mà không cần thiết kế lại kiến trúc HTTPS.

Bên cạnh đó, một số tính năng vẫn đang tiếp tục phát triển:

Structured Concurrency có thể ảnh hưởng đáng kể đến cách lập trình viên Java xây dựng các ứng dụng đồng thời.

Lazy Constants có thể hữu ích với các ứng dụng AI và xử lý dữ liệu chuyên sâu, nơi tài nguyên tốn kém chỉ nên được khởi tạo khi cần.

Tuy nhiên, JDK 27 không phải bản LTS.

Nếu hệ thống production đang chạy một bản LTS như JDK 21 hoặc JDK 25, không cần vội nâng cấp chỉ vì JDK 27 vừa ra mắt. Với dự án mới, thử nghiệm, học tập và đánh giá các khả năng Java sắp tới, JDK 27 là cơ hội phù hợp để tìm hiểu định hướng phát triển của nền tảng.

Kết luận

Java không chỉ phát triển bằng cách bổ sung cú pháp mới.

JDK 27 là một ví dụ điển hình. Những thay đổi quan trọng nhất diễn ra bên dưới ứng dụng:

  • Thu gom rác (Garbage collection).

  • Cấu trúc object (Object layout)

  • Cryptography.

  • Concurrency.

  • Vector hóa CPU

  • Chẩn đoán production

Đó là điều khiến bản phát hành này đáng chú ý.

Bạn có thể giữ nguyên ứng dụng Java, nâng cấp JDK và nhận được những cải thiện đáng kể từ chính môi trường chạy.

Với lập trình viên, câu hỏi thực sự không chỉ là:

“Java 27 có gì mới?” Mà là: “Những thay đổi nào có thể cải thiện hiệu năng khi chạy, bảo mật và kiến trúc ứng dụng mà không buộc tôi phải viết lại ứng dụng?”

JDK 27 có một số câu trả lời đáng kể cho câu hỏi đó.


Chia sẻ:
Liên hệ