Java hiện đại: Tổng quan
Sau bài này, bạn sẽ:
- Hiểu được chu kỳ phát hành mới của Java (time-based releases)
- Nắm được sự khác biệt giữa LTS và non-LTS versions
- Biết được các tính năng chính từ Java 9 đến Java 21
- Hiểu được Module System và lợi ích của nó
- Lên kế hoạch migration giữa các phiên bản Java
Giới thiệu
Java đã trải qua những thay đổi lớn trong cách phát hành và phát triển kể từ năm 2017. Việc hiểu rõ các phiên bản Java hiện đại và tính năng của chúng là quan trọng để viết code hiệu quả và maintainable.
💡 Hình dung: Java release cycle giống như smartphone — mỗi năm có model mới (Java 18, 19, 20...), nhưng chỉ một số là flagship được hỗ trợ lâu dài (LTS: Java 11, 17, 21). Bạn không cần mua flagship mới mỗi năm, nhưng nên upgrade khi flagship hiện tại sắp hết hỗ trợ.
Java Release Cycle (Chu kỳ phát hành)
Trước Java 10: Feature-based releases
Trước khi Java 10 ra mắt, Java có chu kỳ phát hành không cố định:
- Java 7 (2011): Mất 5 năm sau Java 6
- Java 8 (2014): Mất 3 năm sau Java 7
- Java 9 (2017): Mất 3 năm sau Java 8
Từ Java 10 trở đi: Time-based releases
Kể từ Java 10 (March 2018), Oracle áp dụng chu kỳ phát hành mới:
| Đặc điểm | Chi tiết |
|---|---|
| Chu kỳ | 6 tháng/phiên bản |
| Lịch trình | Tháng 3 và Tháng 9 hàng năm |
| Feature freeze | Tính năng không hoàn thành sẽ chuyển sang phiên bản sau |
| Preview features | Các tính năng thử nghiệm, có thể thay đổi |
- Faster innovation: Tính năng mới đến tay developer nhanh hơn
- Predictable schedule: Dễ dàng lên kế hoạch migration
- Smaller changes: Mỗi release ít thay đổi hơn, dễ nâng cấp
- Preview features: Nhận feedback sớm từ cộng đồng
Quy trình phát hành tính năng mới
LTS Versions (Long-Term Support)
Không phải phiên bản nào cũng được hỗ trợ lâu dài. Oracle chỉ chọn một số phiên bản làm LTS.
Các phiên bản LTS
| Phiên bản | Ngày phát hành | End of Support | Tình trạng |
|---|---|---|---|
| Java 8 | March 2014 | December 2030 | LTS (legacy) |
| Java 11 | September 2018 | September 2026 | LTS |
| Java 17 | September 2021 | September 2029 | LTS |
| Java 21 | September 2023 | September 2031 | LTS (latest) |
Các phiên bản không phải LTS (Java 10, 12, 13, 14, 15, 16, 18, 19, 20) chỉ được hỗ trợ 6 tháng cho đến khi phiên bản tiếp theo ra mắt. Chúng KHÔNG phù hợp cho production.
Chu kỳ vòng đời hỗ trợ
Tại sao LTS quan trọng?
// Một công ty sử dụng Java 8 từ 2015
// Năm 2024, họ phải migration sang Java 17 hoặc 21
// Java 8 code
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
names.stream()
.filter(name -> name.startsWith("A"))
.forEach(System.out::println);
// Java 17+ code - có thể dùng text blocks, records, var
var names = List.of("Alice", "Bob", "Charlie"); // Immutable list
names.stream()
.filter(name -> name.startsWith("A"))
.forEach(System.out::println);
Lý do chọn LTS:
- Long-term support: Hỗ trợ bug fixes và security patches lâu dài
- Stability: Phù hợp cho production environments
- Third-party compatibility: Libraries/frameworks hỗ trợ tốt hơn
- Lower migration cost: Không cần upgrade mỗi 6 tháng
Java Version Timeline
Timeline: Java 9 → 21 Highlights
Mindmap: Modern Java Features theo Danh mục
Java 9 (September 2017) - Modularity
// Module System (Project Jigsaw)
module com.example.myapp {
requires java.sql;
exports com.example.myapp.api;
}
// JShell - Java REPL
$ jshell
jshell> int x = 10
x ==> 10
- Module System: Chia ứng dụng thành modules
- JShell: Interactive REPL cho Java
- Collection factory methods:
List.of(),Set.of(),Map.of()
Java 10 (March 2018) - Local Variable Inference
// var keyword
var list = new ArrayList<String>(); // Type inference
var map = Map.of("key", "value"); // Cleaner code
Java 11 (September 2018) - LTS
// New String methods
" Hello ".isBlank(); // false
" Hello ".strip(); // "Hello"
"Java\nKotlin\nScala".lines() // Stream<String>
// var in lambda
(var x, var y) -> x + y
// HttpClient API
var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder()
.uri(URI.create("https://api.example.com"))
.build();
Java 12-13 (2019) - Preview features
// Switch expressions (preview in 12, standard in 14)
var day = switch (dayOfWeek) {
case MONDAY, FRIDAY -> 6;
case TUESDAY -> 7;
default -> throw new IllegalArgumentException();
};
Java 14 (March 2020)
// Switch expressions (standard)
// Records (preview)
record Point(int x, int y) {}
Java 15 (September 2020)
// Text Blocks (standard)
String json = """
{
"name": "Alice",
"age": 30
}
""";
Java 16 (March 2021)
// Records (standard)
record Person(String name, int age) {}
// Pattern matching for instanceof (standard)
if (obj instanceof String s) {
System.out.println(s.toUpperCase());
}
Java 17 (September 2021) - LTS
// Sealed classes (standard)
sealed interface Shape permits Circle, Rectangle, Square {}
final class Circle implements Shape {}
final class Rectangle implements Shape {}
final class Square implements Shape {}
// Pattern matching với sealed classes
double area = switch (shape) {
case Circle c -> Math.PI * c.radius() * c.radius();
case Rectangle r -> r.width() * r.height();
case Square s -> s.side() * s.side();
};
Java 18-20 (2022-2023) - Preview features
- Pattern matching cho switch (preview)
- Virtual threads (preview)
- Structured concurrency (preview)
Java 21 (September 2023) - LTS
// Virtual Threads (standard)
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
executor.submit(() -> System.out.println("Hello from virtual thread"));
}
// Pattern matching for switch (standard)
String formatted = switch (obj) {
case Integer i -> String.format("int %d", i);
case Long l -> String.format("long %d", l);
case Double d -> String.format("double %f", d);
case String s -> String.format("String %s", s);
default -> obj.toString();
};
// Record patterns
record Point(int x, int y) {}
if (obj instanceof Point(int x, int y)) {
System.out.println("x = " + x + ", y = " + y);
}
Migration Considerations
Java 8 → Java 11
| Thay đổi | Impact | Action |
|---|---|---|
| Java EE modules removed | javax.xml.bind, javax.activation không còn | Thêm dependencies riêng |
| Nashorn deprecated | JavaScript engine cũ | Dùng GraalVM hoặc alternatives |
| Security changes | TLS 1.0/1.1 disabled | Upgrade protocols |
| Performance | G1GC mặc định | Review GC settings |
// Java 8 - JAXB có sẵn
import javax.xml.bind.JAXBContext;
// Java 11 - Cần thêm dependency
// pom.xml
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.1</version>
</dependency>
Java 11 → Java 17
// Có thể dùng:
// - Records thay vì POJOs
// - Sealed classes cho domain modeling
// - Pattern matching cho instanceof
// - Text blocks cho multi-line strings
// Before (Java 11)
public class Person {
private final String name;
private final int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// getters, equals, hashCode, toString...
}
// After (Java 17)
public record Person(String name, int age) {}
- Update dependencies: Frameworks cần phiên bản hỗ trợ Java mới
- Test thoroughly: Chạy full test suite
- Check third-party libraries: Một số library cũ không tương thích
- Review deprecations:
@Deprecated(forRemoval=true)
Java 17 → Java 21
// Virtual threads - game changer cho concurrent applications
// Before: Platform threads
ExecutorService executor = Executors.newFixedThreadPool(100);
// After: Virtual threads
ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor();
Key benefits:
- Virtual threads cho high-throughput I/O
- Pattern matching improvements
- Sequenced collections
Module System (Java 9) - Giới thiệu ngắn
Tại sao cần Module System?
Vấn đề trước Java 9:
- Classpath hell: Conflict giữa các versions của libraries
- No encapsulation: Tất cả public classes đều accessible
- Large JRE: JRE chứa nhiều modules không cần thiết
Module cơ bản
// module-info.java
module com.example.app {
// Khai báo dependencies
requires java.sql;
requires java.logging;
// Export packages (public API)
exports com.example.app.api;
// Internal packages không export
// com.example.app.internal - not accessible
}
Ưu điểm
- Strong encapsulation: Chỉ export những gì cần thiết
- Reliable configuration: Compile-time dependency checking
- Smaller runtime: Chỉ include modules cần thiết
- Better performance: JVM optimization
Module System — Deep Dive
Kiến trúc Module System
Các directive trong module-info.java
module com.example.app {
// requires — khai báo dependency
requires java.sql; // Phụ thuộc java.sql
requires transitive java.logging; // Transitive: module dùng app cũng thấy logging
requires static java.compiler; // Optional: chỉ cần lúc compile
// exports — public API
exports com.example.app.api; // Cho TẤT CẢ modules thấy
exports com.example.app.spi to // Chỉ cho modules cụ thể thấy
com.example.plugin;
// opens — cho phép reflection (runtime access)
opens com.example.app.model; // Cho TẤT CẢ — cần cho Jackson, Hibernate
opens com.example.app.config to // Chỉ cho Spring Framework
spring.core, spring.beans;
// uses/provides — ServiceLoader pattern
uses com.example.app.spi.Plugin;
provides com.example.app.spi.Plugin
with com.example.app.DefaultPlugin;
}
requires transitive — Truyền dependency
// module com.example.lib
module com.example.lib {
requires transitive java.sql; // Transitive!
exports com.example.lib.db;
}
// module com.example.app
module com.example.app {
requires com.example.lib;
// KHÔNG cần "requires java.sql" — đã có transitive từ lib
// Code trong app CÓ THỂ dùng java.sql classes
}
Unnamed Module và Automatic Module
| Loại module | Mô tả | Khi nào gặp |
|---|---|---|
| Named module | Có module-info.java | Project mới, JDK modules |
| Automatic module | JAR trên module-path, tên từ filename | Library chưa modularize |
| Unnamed module | Code trên classpath (cũ) | Legacy code |
# Kiểm tra dependencies với jdeps
jdeps --module-path libs -s myapp.jar
# Thêm quyền truy cập khi bị module system chặn
java --add-opens java.base/java.lang=ALL-UNNAMED MyApp
# Tạo custom runtime image (chỉ chứa modules cần thiết)
jlink --module-path $JAVA_HOME/jmods:myapp.jar \
--add-modules com.example.app \
--output custom-jre
# custom-jre chỉ ~30MB thay vì ~300MB full JDK!
Migration Gotchas
// 1. Split packages — cùng package trong 2 modules
// ❌ Error: Package com.example.util exists in both moduleA and moduleB
// Fix: Merge hoặc rename packages
// 2. Reflection access bị chặn
// ❌ InaccessibleObjectException từ Java 16+
// Fix: --add-opens hoặc "opens" directive
// 3. Internal APIs bị chặn
// ❌ sun.misc.Unsafe không accessible
// Fix: Dùng VarHandle (Java 9+) thay thế
import java.lang.invoke.VarHandle;
requires transitive truyền dependency cho module phụ thuộc. Nếu module A requires transitive module B, thì module C chỉ cần requires module A là đã thấy module B.
Unnamed module có thể đọc TẤT CẢ named modules, nhưng named module KHÔNG THỂ requires unnamed module. Đây là lý do migration từ classpath sang module-path phải làm từ dưới lên.
@Deprecated(forRemoval=true) khác @Deprecated(since="9"):
forRemoval=true: Sẽ bị XOÁ trong phiên bản tương lai → compiler warning mạnh hơnsince="9": Chỉ đánh dấu deprecated từ version 9, chưa chắc sẽ bị xoá
@Deprecated(since="9", forRemoval=true)
public class SecurityManager { ... } // SẼ bị xoá (removed in Java 24)
@Deprecated(since="9")
public class Observable { ... } // Deprecated nhưng CHƯA CHẮC bị xoá
Oracle khuyến nghị migration theo từng bước: (1) compile với --release flag để phát hiện removed APIs, (2) dùng jdeps để phân tích dependencies, (3) thêm --add-opens cho reflection access, (4) tạo module-info.java khi sẵn sàng.
Tham khảo: Oracle Migration Guide
Module system là optional. Bạn có thể chạy code Java 9+ mà không cần modules (unnamed module). Tuy nhiên, trong dự án lớn, modules giúp quản lý dependencies tốt hơn.
Deprecated Features cần biết
Removed trong Java 11+
- Applets: Hoàn toàn removed
- Java Web Start: Removed
- CORBA: Removed
- JavaFX: Tách ra thành dự án riêng
Deprecated trong Java 21
// Finalization - deprecated for removal
@Override
protected void finalize() throws Throwable {
// DON'T USE - use try-with-resources instead
}
// Better approach
class Resource implements AutoCloseable {
@Override
public void close() {
// Cleanup logic
}
}
try (var resource = new Resource()) {
// Use resource
} // Automatically closed
Kết luận
| Nếu bạn đang dùng | Nên upgrade lên | Lý do |
|---|---|---|
| Java 8 | Java 17 | LTS, modern features, performance |
| Java 11 | Java 21 | Latest LTS, virtual threads |
| Java 17 | Java 21 | Virtual threads, pattern matching improvements |
| Non-LTS (12-16, 18-20) | Java 21 | End of support |
- Production: Luôn dùng LTS version (hiện tại là Java 17 hoặc 21)
- Learning: Thử nghiệm với latest version để học tính năng mới
- Migration: Lên kế hoạch migration từ sớm, test kỹ trước khi production
Tính năng chi tiết trong module này
Các bài tiếp theo sẽ đi sâu vào từng tính năng:
| Tính năng | Bài học | Java Version |
|---|---|---|
var — Local Variable Type Inference | var keyword | Java 10 |
| Text Blocks | Text Blocks | Java 15 |
| Records | Records | Java 16 |
| Sealed Classes | Sealed Classes | Java 17 |
| Pattern Matching | Pattern Matching | Java 16-21 |
| Virtual Threads | Virtual Threads | Java 21 |