backend

Java17 - String 클래스의 최적화

downfa11 2025. 2. 25. 22:31

기존 JDK(17 이하)와 달라진 Stirng 클래스의 최적화에 대해 알아보자.

 

크게 배워야할 부분은 없고 3가지 특징으로 구분할 수 있다. 

String 관련 성능이 기존보다 훨씬 최적화되었다. (메모리 절약 + 실행 성능 향상 + GC 부담 감소)

 

1. Compact Strings 유지

Java8까지만 해도 String 객체는 내부적으로 char[] (2byte UTF-16 인코딩)을 사용함

 

Java9부터 Compact Strings 기법을 도입. byte[] + coder 플래그를 사용해서 1byte 문자 저장해서 메모리 절약

→ 한글이나 중국어같은 다국어는 UTF-16(2byte) 유지, 영어나 숫자는 1byte로 저장

  1. Heap 공간을 적게 차지해서 GC 성능 최적화
  2. 작은 크기의 문자열을 더욱 빠르게 처리하기 때문에 캐시 효율 증가
  3. 영문 문자열 사용시 최대 50% 메모리 감소

 

2. 인턴 풀(Intern Pool) 개선

Java 8~11까지는 String.intern()에서 JVM의 String Pool에 문자열을 저장하고 재사용했다.

 

String.intern()이란?

String.intern()은 JVM의 String Constant Pool(문자열 상수 풀)에 문자열을 저장하고, 동일한 문자열이 존재하면 해당 객체를 재사용한다

같은 문자열 리터럴이 여러 번 사용될때 메모리를 절약하기 위해 String Constant Pool을 사용한다.

new String()로 생성된 문자열은 String Constant Pool에 들어가지 않는다.

이때 수동으로 문자열 풀에 넣는게 intern()이다.

 

String.intern()의 동작과정

  1. new String()으로 Heap 영역에 새로운 객체 생성
  2. intern()을 호출하면 해당 문자열이 String Constant Pool에 있는지 확인
  3. 있으면 그 객체를 반환, 없으면 새로 추가하고 반환

 

JDK 17 이후로 최적화된 String.intern()

많은 문자열을 인턴(intern)하면 메타스페이스(metaspace) 오버헤드가 증가한다.

기존 JVM에서는 특히 metaspace 크기가 작아서 대량의 intern()시 OOM 발생 가능

  • Java17에서 metaspace의 인턴 풀을 자동 관리 → OOM 방지
  • 더 효율적인 해시 테이블 구조 → intern된 문자열 검색 속도 향상
  • GC와 효율적인 연동 → 사용되지 않는 intern된 문자열 정리 최적화

 

3. StringConcatFactory 개선

Java9에서 도입된 StringConcatFactory가 Java17에서 더 최적화됨

Java8까지는 StringBuilder.append() 방식으로 문자열을 이어붙이는데, 많은 문자열을 연결하면 GC 부담이 증가했다.

 

Java 9 ~17의 StringConcatFactory

문자열을 연결하는 방식이 invoedynamic기반의 StringConcatFactory으로 변경

Java 17에서는 더 최적화된 네이티브 코드로 변환하여 성능 향상(JIT 컴파일러 빠르게 실행)

 

String str = "Hello" + "JVM" + "Performance";