String과 메모리

1 분 소요

1. 문자열 생성 방식과 메모리 위치

자바에서 String을 생성하는 방법은 두가지가 있다.
String 생성 방법에 따라서 메모리 저장위치가 달라진다.

1.1 new 연산자로 생성

String name = new String("이름");

new를 통해 String을 생성할 경우 메모리의 Heap 영역에 존재하게 된다.

1.2. 리터럴로 생성

String name = "이름"

리터럴을 이용하여 생성한 경우 메모리의 string constant pool이라는 영역에 존재하게 된다.

2. string constant pool

많은 String object가 중복 생성되는것을 방지하기 위해 JVM에는 string constant pool(string literal pool) 이라는 영역이 존재한다.

만약 문자열을 리터럴로 생성할 경우 우선 이 pool을 찾아 동일한 String이 있는지 확인하여 중복 생성을 방지하고 pool에 없을 경우 새로운 문자열을 생성하여 pool에 추가한다.

3. 문자열 비교에 대한 고찰

문자열 비교시 == 연산자를 사용하지 않고 equal() 메서드를 사용한다.
== 연산자의 경우 문자열 객체가 존재하는 메모리 위치를 비교하고, equal() 메서드는 문자열의 값 자체를 비교하기 때문이다.

그렇다면 아래의 결과는 어떻게 될까?

public void test1() {
    String name1 = "이름1";
    System.out.println("결과는 : " + (name1 == "이름1"));
}

public void test2() {
    String name2 = new String("이름2");
    System.out.println("결과는 : " + (name2 == "이름2"));
}

위 결과에서 첫번째는 true, 두번째는 false가 리턴된다.

3.1. test1

  • name1 : 메서드 내의 변수이므로 stack에 생성된다. 만약 class의 멤버변수 였다면 객체가 생성될때 heap에 생성되었을 것이다.
  • 이름1 : 모든 객체는 heap에 생성된다. 이름1 문자열 객체 역시 heap에 생성되는데, 문자열 리터럴로 생성되었기 때문에 생성된 heap의 위치는 string constant pool에 저장된다.
  • 결국 stack에 생성된 name1은 heap에 생성된 이름1의 주소를 가리키고 있고, 이 주소값은 string constant pool에 저장된다. 두번째 결과를 확인하는 과정에서 이름1은 이미 그 전에 생성된적이 있어 string constant pool에 들어가있고 이 값은 name1 이 가리키는 주소와 동일하기에 true가 리턴된다.

3.2. test2

  • name2 : 첫번째와 동일하게 메서드 내의 변수이므로 stack에 생성된다.
  • 이름2 : 첫번째와 동일하게 heap에 우선 생성된 후 string constant pool에 저장된다.
  • new String() : new 연산자로 새롭게 객체를 생성한다. 따라서 heap 영역에 또 다른 메모리 공간을 할당해 객체를 생성한다. 내부적으로는 이름2 를 가리키고 있을것이지만 여기를 가리키는 또 다른 객체가 생성된 것이다.
  • 결과 비교시 name2는 이미 새롭게 heap에 할당된 곳을 가리키기 때문에 string constant pool의 이름2가 가리키는 곳과 다른 주소값을 가진다. 따라서 false가 리턴된다.

[참고 문서]

카테고리:

업데이트:

댓글남기기