///////
Search
🥭

Java Compiler는 문자열 연산 최적화를 어떻게 진행하나요? (String Builder, String...)

~ JDK 1.4
문자열 연산 시 매 연산마다 문자열 객체 생성
~JDK 8
String 연산 작업을 StringBuilder를 이용해 바이트 코드를 변경하여 최적화
변수 e에서 보이듯이 두 개의 큰따옴표로 더하기 연산을 하면 컴파일 시점에 합쳐져서 하나의 문자열이 된다.
a 변수에 할당한 것처럼 b + c + d의 문자열 객체 연산이 일어나면 StringBuilder로 바이트 코드를 조작해 컴파일 시점에 최적화를 해준다.
기존에 있던 b라는 변수("Hello ")에 큰따옴표를 이용해 문자열("World")을 결합시키면 큰따옴표로 감싸진 문자열("World")은 String Pool에 저장된다.
c 변수에 "World" 문자열을 저장했지만 String Constant Pool에 먼저 등록된 "World" 라는 문자열을 가져온다.
컴파일러가 자동으로 최적화를 해준다고 하더라도 연산 최적화는 직접 하는 것이 바람직하다.
JDK 9 ~
런타임 시점에 String을 연산, invokedynamic을 사용하도록 변경
→ 재컴파일 없이도 런타임시 최적화된 새로운 전략을 적용 가능
런타임시 문자열 결합 전략을 받아 수행
과정
문자열 결합 전략
BC_SB (ByteCode StringBuilder) : 런타임 시 동일한 StringBuilder 바이트코드를 생성
BC_SB_SIZED : StringBuilder에 필요한 용량을 추측하려고 시도한다. 그 외에는 이전 방식과 동일
BC_SB_SIZED_EXACT : StringBuilder를 사용하고, 필요한 용량을 정확히 계산. 필요한 용량을 계산하기 위해 모든 인수를 문자열로 변환(int -> toString)
MH_SB_SIZED : MethodHandle을 기반으로 하고 StringBuilder API를 호출
MH_SB_SIZED_EXACT : 이전과 유사하지만 StringBuilder의 용량을 정확히 계산
MH_INLINE_SIZE_EXACT : 필요한 용량을 미리 계산하고, 전달된 인자들을 연결하여 byte 배열로 생성 후, String의 private 생성자를 이용하여 copy 없이 byte 배열을 전달하여 String 객체를 반환

결론

JDK 8까지는 StringBuilder 객체 생성 후 컴파일 시점에 바이트코드를 변경하여 최적화
JDK 9부터는 런타임 시 문자열 결합 전략을 받아 수행