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
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
executor.submit(() -> fetchUser(id));
Future
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
scope.fork(() -> fetchUser(id));
Supplier
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 đó.










