Java

[Java] Java 21 특징

kittity 2025. 1. 31. 00:40

Java 21은 2023년 9월에 출시된 LTS(Long Term Support) 버전으로 Java 21에서 추가된 기능과 특징에 대해 정리해보고자한다.

주요 특징에 대해 정리하면 다음과 같다. Preview는 제외하였다.

  1. JEP 431 : Sequenced Collections (https://openjdk.org/jeps/431)
  2. JEP 439: Generational ZGC (https://openjdk.org/jeps/439)
  3. JEP 440: Record Patterns (https://openjdk.org/jeps/440)
  4. JEP 441: Pattern Matching for switch (https://openjdk.org/jeps/441)
  5. JEP 444: Virtual Threads (https://openjdk.org/jeps/444)
  6. JEP 449: Deprecate the Windows 32-bit x86 Port for Removal (https://openjdk.org/jeps/449)
  7. JEP 451: Prepare to Disallow the Dynamic Loading of Agents (https://openjdk.org/jeps/451)
  8. 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);
    }
}

 

728x90