Java/문자열

[Java]문자열 상수 풀(String Constant Pool)이란?

DevStory 2022. 5. 19.

문자열 상수 풀(String Constant Pool)

Java는 문자열 상수 풀 또는 문자열 풀이라고 불리는 특수한 저장 공간을 가지고 있습니다. 문자열 상수 풀은 Java의 힙 영역에 존재하는 특수한 공간으로 문자열 리터럴을 저장하는 용도로 사용됩니다.

 

문자열 리터럴이 생성될 때마다 JVM은 해당 문자열이 문자열 상수 풀에 존재하는지 확인합니다. 문자열 상수 풀에 해당 문자열이 존재하지 않으면, 해당 문자열을 문자열 상수 풀에 저장하고 존재하면 저장하지 않습니다.

 

위 내용을 이해하기 쉽게 다음 소스 코드를 살펴봅시다.

int num = 10;
boolean bool = false;
String str = "Hello";

Java의 기본 타입(byte, char, short, int, boolean, long 등.. )은 스택(Stack)에 저장됩니다.

반면에, 참조 타입의 데이터는 힙(Heap)에 저장됩니다. 스택에 존재하는 변수는 힙에 존재하는 데이터를 참조합니다.

 

위 소스 코드를 그림으로 나타내면 다음과 같습니다.

변수 num과 bool은 기본 타입이므로 데이터가 스택 영역에 존재합니다. 하지만, 변수 str의 타입은 String이므로 실제 데이터는 힙 영역에 존재하는 문자열 상수 풀에 존재합니다.


문자열 생성 방법 1. 문자열 리터럴

문자열 리터럴은 문자열을 생성할 수 있는 가장 기본적인 방법입니다.

public static void main(String args[]) {
  String str1 = "Hello";
  String str2 = "World";
  String str3 = "Hello";
}

[문자열 풀 동작 과정]

순서 1. 프로그램이 실행되면, 문자열 상수 풀은 기본적으로 비어 있습니다. 따라서, 문자열 상수 풀에 문자열 "Hello"가 저장됩니다.

순서 2. JVM은 문자열 변수 str2에 문자열 "World"를 할당하기 전에 문자열 상수 풀에 문자열 "World"가 존재하는지 확인합니다. 문자열 상수 풀에 문자열 "World"가 존재하지 않으므로 문자열 "World"가 문자열 상수 풀에 저장되고 문자열 변수 str2는 참조 값을 가집니다.

순서 3. 첫 번째 순서에서 "Hello"라는 문자열이 문자열 상수 풀에 저장되었으므로 문자열 변수 str3는 동일한 참조 값을 가집니다.

 

위 소스 코드를 그림으로 나타내면 다음과 같습니다.


문자열 생성 방법 2. new 키워드

문자열 리터럴 방식으로 문자열을 생성하면, 문자열은 문자열 상수 풀에 저장됩니다. 하지만, new 키워드를 사용하여 생성된 문자열은 문자열 상수 풀 외부 영역에 저장됩니다.

public static void main(String args[]) {
  String str1 = "Hello";
  String str2 = new String("Hello");
  String str3 = new String("Hello");
}

new 키워드를 사용하여 생성된 문자열은 동일한 문자열이라도 힙 영역에 여러 개 생성됩니다.

 

위 소스 코드를 그림으로 나타내면 다음과 같습니다.


문자열 생성 방법 3. String 클래스의 intern 메서드

문자열을 생성하는 세 번째 방법으로 intern() 메서드를 사용할 수 있습니다.

 

저는 문자열 상수 풀을 다음과 같이 설명했습니다.

 

"문자열 리터럴이 생성될 때마다 JVM은 해당 문자열이 문자열 상수 풀에 존재하는지 확인합니다. 문자열 상수 풀에 해당 문자열이 존재하지 않으면, 해당 문자열을 문자열 상수 풀에 저장하고 존재하면 저장하지 않습니다."

 

intern() 메서드는 위 내용을 수행하는 메서드입니다. new 키워드로 문자열을 생성하더라도 해당 문자열이 문자열 상수 풀에 존재하는지 확인합니다. 문자열 상수 풀에 해당 문자열이 존재하지 않으면, 해당 문자열을 문자열 상수 풀에 저장하고 존재하면 저장하지 않습니다.

public static void main(String args[]) {
  String str1 = "Hello";
  String str2 = new String("Hello").intern();
  String str3 = new String("Hello");

  System.out.println(str1 == str2);
  System.out.println(str1 == str3);
}

[실행 결과]

true
false

== 연산자를 사용하여 문자열 리터럴을 사용한 변수 str1이랑 intern() 메서드를 사용한 변수 str2를 비교하면 true가 반환되는 것을 확인할 수 있습니다.

 

반면에 문자열 리터럴을 사용한 변수 str1이랑 new 키워드로 사용한 변수 str3을 비교하면 false가 반환됩니다.

 

위 소스 코드를 그림으로 나타내면 다음과 같습니다.


문자열 상수 풀 장점

  • 문자열 상수 풀에 동일한 문자열이 이미 존재하는 경우 새로운 문자열을 생성하지 않으므로 메모리 공간을 절약합니다.
  • 문자열 상수 풀은 문자열 캐싱을 사용하므로 JVM은 문자열이 문자열 상수 풀에 존재하는지 빠르게 확인할 수 있습니다.
반응형

댓글