JDK 25, 문자열 처리 성능이 대폭 향상됐다
자바에서 String은 모든 프로젝트에서 핵심 역할을 합니다. 로그 메시지부터 데이터 키 관리, 네트워크 통신까지 대부분의 기능에 문자열이 관여하죠. 그렇기 때문에 String 성능 개선은 곧 애플리케이션 전반의 효율성과 직결됩니다.
JDK 25에서는 String::hashCode의 성능이 크게 개선됐습니다. 특히, 상수 문자열을 키로 사용하는 Map 구조에서 성능 향상이 두드러집니다. 이 블로그에서는 이번 개선이 어떤 방식으로 이루어졌는지, 실제 코드에 어떤 영향을 미치는지, 개발자가 주의해야 할 점은 무엇인지 살펴보겠습니다.
String::hashCode 개선이란 무엇인가?
기존에는 String 객체의 해시코드가 처음 호출될 때 계산되고, 그 값을 내부 필드에 저장하는 방식이었습니다. 이 저장된 해시코드는 String이 불변(immutable)이기 때문에 다시 계산할 필요 없이 그대로 재사용할 수 있습니다.
JDK 25에서는 이 내부 필드(String.hash)에 @Stable이라는 JDK 내부 전용 주석을 추가했습니다. 이 한 줄의 변화가 성능을 획기적으로 끌어올렸습니다.
@Stable, 단 한 줄의 변화로 이뤄낸 성능 개선
@Stable 주석은 JVM에게 “이 값은 바뀌지 않는다”고 알려주는 역할을 합니다. 만약 이 값이 0이 아닌 초기값으로 설정되면, JVM은 이후 이 값을 신뢰하고 더 이상 검증하지 않습니다. 이렇게 되면 다음과 같은 최적화가 가능해집니다:
- 문자열 해시코드를 미리 알고 있기 때문에 hashCode() 호출을 생략 가능
- 이 해시코드를 기반으로 Map에서 키를 조회할 때, Map 내부에서 어떤 인덱스를 참조할지 미리 계산 가능
- 해당 인덱스에 저장된 값을 바로 접근할 수 있어 탐색 시간이 획기적으로 단축됨
결과적으로, 일련의 연산들이 사전에 계산된 고정된 연산으로 변환되며 런타임 시점에 더 이상 연산을 하지 않아도 됩니다.
예제 코드: 실제로 어떻게 활용되는가?
다음은 System Call을 Java 코드에서 관리하는 고급 예제입니다. 이 예제는 상수 문자열을 키로 하는 불변 Map을 활용하며, 개선된 String 성능이 어떻게 발휘되는지 보여줍니다.
// 시스템 호출 이름을 키로 하는 불변 Map 생성
static final Map<String, MethodHandle> SYSTEM_CALLS = Map.of(
"malloc", linker.downcallHandle(mallocSymbol, ...),
"free", linker.downcallHandle(freeSymbol, ...)
);
// 16바이트 메모리 할당
long address = SYSTEM_CALLS.get("malloc").invokeExact(16L);
// 메모리 해제
SYSTEM_CALLS.get("free").invokeExact(address);
여기서 핵심은 SYSTEM_CALLS.get("malloc")과 같은 상수 문자열 조회가 @Stable 최적화 덕분에 상수 시간에 수행될 수 있다는 점입니다.
실제 성능 측정 결과는 다음과 같습니다:
비전 | 평균 수행 시간 (ns/op) |
JDK 24 | 4.632 |
JDK 25 | 0.571 |
거의 8배 이상 성능 향상이 일어났으며, 이는 문자열 해시코드 계산 및 Map 조회 과정이 모두 상수화됐기 때문입니다.
유의사항: 모든 경우에 적용되는 것은 아니다
이 성능 개선에는 한 가지 예외가 있습니다. 바로 hashCode가 0인 문자열입니다. 자바의 @Stable은 초기값이 아닌 경우에만 상수화가 가능하므로, 0이라는 기본값을 가진 해시코드는 최적화되지 않습니다.
예를 들어, "" (빈 문자열)의 해시코드는 0입니다. 이 때문에 빈 문자열은 해당 최적화의 적용 대상이 아닙니다. 다만, 일반적인 문자열(1~6자의 알파벳, 공백 등)은 대부분 0이 아닌 해시코드를 가지므로, 실사용에서는 큰 문제가 되지 않습니다.
사용자 코드에서는 어떻게 활용할 수 있을까?
@Stable 주석은 JDK 내부 코드에서만 사용할 수 있습니다. 하지만 앞으로 출시될 **JEP 502: Stable Values (Preview)**를 통해 일반 사용자 코드에서도 간접적으로 안정값(stable value)의 이점을 누릴 수 있도록 준비 중입니다.
이러한 기능이 도입되면, 고정값 기반의 구조나 설정 데이터를 더욱 효율적으로 다룰 수 있게 될 것입니다.
JDK 25의 String 최적화는 단순한 내부 개선을 넘어, 실질적으로 Java 개발자들이 자주 사용하는 Map<String, V> 구조의 성능을 비약적으로 향상시킵니다. 특히, 상수 문자열 키와 불변 맵을 사용하는 코드는 아무런 수정 없이도 큰 성능 이득을 얻게 됩니다.
이 개선이 의미하는 바는 분명합니다:
- JDK 내부 최적화는 이제 더 이상 단순한 "엔진 개선"이 아니라, 개발자의 코드 실행 방식에 실질적인 영향을 준다.
- 고정된 값과 불변 객체의 사용은 앞으로 성능 측면에서 더욱 권장될 것이다.
- 단순히 “잘 돌아가는 코드”를 넘어, “더 잘 돌아가는 코드”를 고민할 시점이 되었다.
Java 21이나 22를 사용 중이라면, JDK 25로의 업그레이드를 진지하게 고려해볼 만한 이유가 하나 더 생긴 셈입니다.
https://inside.java/2025/05/01/strings-just-got-faster/
Strings Just Got Faster – Inside.java
In JDK 25, Strings used as keys in immutable Maps can be much faster.
inside.java
'JAVA' 카테고리의 다른 글
자바 30주년: 세상을 바꾼 코드, 그리고 그 천재의 이야기 (0) | 2025.05.19 |
---|---|
Java 24 출시! 개발자를 위한 주요 기능 및 예제 정리 (0) | 2025.03.26 |
JDK 24 출시! 새로운 기능과 주요 개선 사항 정리 (0) | 2025.03.19 |
Java 애플리케이션 성능 최적화: 성능 저하 요인과 해결 방법 총정리 (0) | 2025.03.19 |
Java 23: 새로운 기능과 예제 총정리 (0) | 2025.01.07 |