본문 바로가기

JAVA

“JDK 25에서 문자열이 8배 빨라졌다?” String 최적화의 모든 것

728x90
반응형

 

https://inside.java/2025/05/01/strings-just-got-faster/

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)의 이점을 누릴 수 있도록 준비 중입니다.

이러한 기능이 도입되면, 고정값 기반의 구조나 설정 데이터를 더욱 효율적으로 다룰 수 있게 될 것입니다.


728x90

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

728x90
반응형