Java 21은 2023년 9월에 출시된 LTS(Long Term Support) 버전으로 Java 21에서 추가된 기능과 특징에 대해 정리해보고자한다.
주요 특징에 대해 정리하면 다음과 같다. Preview는 제외하였다.
- JEP 431 : Sequenced Collections (https://openjdk.org/jeps/431)
- JEP 439: Generational ZGC (https://openjdk.org/jeps/439)
- JEP 440: Record Patterns (https://openjdk.org/jeps/440)
- JEP 441: Pattern Matching for switch (https://openjdk.org/jeps/441)
- JEP 444: Virtual Threads (https://openjdk.org/jeps/444)
- JEP 449: Deprecate the Windows 32-bit x86 Port for Removal (https://openjdk.org/jeps/449)
- JEP 451: Prepare to Disallow the Dynamic Loading of Agents (https://openjdk.org/jeps/451)
- JEP 452: Key Encapsulation Mechanism API (https://openjdk.org/jeps/452)
위의 항목을 하나씩 살펴보자.
1. JEP 431 : Sequenced Collections
순서가 있는 컬렉션을 표현하기 위해 새로운 인터페이스가 도입되었다. 기존 자바 컬렉션 프레임워크는 아래 표와 같이 첫 요소나 마지막 요소를 가져오는 방식이 컬렉션마다 다르며, 역순으로 순회하는 방법에 컬렉션마다 다르거나 아예 없는 경우도 있다.
First | element | Last element |
List | list.get(0) | list.get(list.size() - 1) |
Deque | deque.getFirst() | deque.getLast() |
SortedSet | sortedSet.first() | sortedSet.last() |
LinkedHashSet | linkedHashSet.iterator().next() | // missing |
이로 인해 SequencedCollections, SequencedSet, SequencedMap이라는 새로운 인터페이스가 도입되었고 동일한 방식으로 첫 요소와 마지막 요소에 접근이 가능하며 역순 처리도 지원한다.
SequencedCollection 인터페이스를 살펴보면 역순처리와 첫/마지막 요소의 추가, 조회, 삭제를 제공하는 것을 알 수 있다.
interface SequencedCollection<E> extends Collection<E> {
// new method
SequencedCollection<E> reversed();
// methods promoted from Deque
void addFirst(E);
void addLast(E);
E getFirst();
E getLast();
E removeFirst();
E removeLast();
}
LinkedHashSet의 역순 처리를 다음과 같이 간단하게 할 수 있게 되었다.
linkedHashSet.reversed().stream()
SequencedSet 인터페이스는 다음과 같다.
interface SequencedSet<E> extends Set<E>, SequencedCollection<E> {
SequencedSet<E> reversed(); // covariant override
}
SequencedMap 인터페이스는 다음과 같다.
interface SequencedMap<K,V> extends Map<K,V> {
// new methods
SequencedMap<K,V> reversed();
SequencedSet<K> sequencedKeySet();
SequencedCollection<V> sequencedValues();
SequencedSet<Entry<K,V>> sequencedEntrySet();
V putFirst(K, V);
V putLast(K, V);
// methods promoted from NavigableMap
Entry<K, V> firstEntry();
Entry<K, V> lastEntry();
Entry<K, V> pollFirstEntry();
Entry<K, V> pollLastEntry();
}
이 3가지 인터페이스는 기존 컬렉션 계층에 다음과 같이 적용되었다.
- List와 Deque는 SequencedCollection을 구현
- LinkedHashSet은 SequencedSet을 구현
- SortedSet은 SequencedSet을 구현
- LinkedHashMap은 SequencedMap을 구현
- SortedMap은 SequencedMap을 구현
또한 세 가지 새로운 타입에 대한 수정 불가능한 래퍼를 생성하기 위해 Collections 유틸리티 클래스에 새로운 메서드들이 추가되었다.
- Collections.unmodifiableSequencedCollection(sequencedCollection)
- Collections.unmodifiableSequencedSet(sequencedSet)
- Collections.unmodifiableSequencedMap(sequencedMap)
2. JEP 439: Generational ZGC
Java15 부터 기본 GC는 ZGC로 채택되었다. ZGC를 개선하여 객체를 young과 old 두 세대로 나누어 관리하는 가비지 컬렉터가 Generational ZGC이다.
young 객체를 old 객체보다 더 자주 수집하도록 하였는데, 그 이유는 young 객체들은 수명이 짧다는 가설인 약한 세대 가설(Weak Generational Hypothesis)에있다. 이에 따르면 young 객체를 수집하는데 필요한 리소스가 적고 메모리가 많은 반면, old 객체를 수집하는데 필요한 리소스가 더 많고 메모리가 적기 때문에 젊은 객체를 더 자주 수집하면 ZGC를 사용하는 애플리케이션의 성능을 개선할 수 있다는 것이다.
사용 방법은 다음과 같다.
$ java -XX:+UseZGC -XX:+ZGenerational ...
Java21에서는 원활한 계승을 위해 ZGC와 함께 Generational ZGC를 함께 사용할 수 있도록 제공한다. 위 명령을 참고하면 된다. 이후 릴리즈에는 Generational ZGC를 기본값으로 설정할 것이라고 한다.
3. JEP 440: Record Patterns
Record Patterns는 record 클래스의 인스턴스를 분해하여 내부 데이터에 쉽게 접근할 수 있는 기능이다. 특히, 패턴을 중첩해서 사용할 수 있어 복잡한 데이터 구조도 선언적이고 간결하게 처리할 수 있다.
다음 예시를 살펴보자.
Java16 이전의 경우, 다음과 같이 내장된 접근자 메서드를 통해 데이터를 추출할 수 있었다.
// As of Java 16
record Point(int x, int y) {}
static void printSum(Object obj) {
if (obj instanceof Point p) {
int x = p.x();
int y = p.y();
System.out.println(x+y);
}
}
반면, Java21 부터는 레코드 패턴을 통해 다음과 같은 방식이 가능하다.
// As of Java 21
static void printSum(Object obj) {
if (obj instanceof Point(int x, int y)) {
System.out.println(x+y);
}
}
'Java' 카테고리의 다른 글
[Java] Checked Exception과 Unchecked Exception (0) | 2025.03.06 |
---|---|
[Java] 비동기 처리를 위한 CompletableFuture 완벽 가이드 (0) | 2025.03.06 |
[Java] Java 17 특징 (1) | 2025.01.30 |
[Java] Java 11 특징 (0) | 2025.01.30 |
[실전 자바 - 기본편] 다형성2 (0) | 2024.09.09 |