기존 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로 저장
- Heap 공간을 적게 차지해서 GC 성능 최적화
- 작은 크기의 문자열을 더욱 빠르게 처리하기 때문에 캐시 효율 증가
- 영문 문자열 사용시 최대 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()의 동작과정
- new String()으로 Heap 영역에 새로운 객체 생성
- intern()을 호출하면 해당 문자열이 String Constant Pool에 있는지 확인
- 있으면 그 객체를 반환, 없으면 새로 추가하고 반환
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";
'backend' 카테고리의 다른 글
Java도 한다 경량 쓰레드 (Virtual Thread) (0) | 2025.02.26 |
---|---|
JVM의 Garbage Collector 분석 (feat. ZGC와 G1간의 차이점 비교) (0) | 2025.02.26 |
Tomcat, Netty의 쓰레드 덤프 분석을 통해 병목 지점을 분석해보자 - Prometheus,Grafana를 통한 시각화 모니터링 (1) | 2025.02.24 |
스프링에서 제공하는 Redis 직렬화/역직렬화 도구의 한계와 직접 구현 (Snappy 압축) (0) | 2025.02.19 |
Hexagonal Architecture의 테스트코드 작성 (feat. StepVerifier, TestPublisher) (0) | 2025.02.13 |