Java에서 String 객체를 생성하는 방법에는 두 가지가 있다.
//1번째 방법 ->literal
String str1 = "hello";
String str2 = "hello";
//2번째 방법 ->new
String str3 = new String("hello");
이 두 가지의 방법은 메모리 생성에서 차이가 있다.
위 코드의 str1과 str2(literal)의 경우 Heap의 String Constant Pool에 할당이 되고, str3(new)의 경우 Heap 내부에 할당이 된다는 것이다.
String을 literal 방식(String str = "###")으로 선언하였을 때 문자열 형식의 상수를 집어넣는 공간이다.
String Constant Pool에 문자열을 집어넣는 것을 String interning 이라고 한다.
이렇게 되면 String을 literal 방식으로 생성하였을 때 "hello"라는 값이 할당된 메모리 주소를 참조하게 된다.
그러면 위 코드에서 str1과 str2가 같은 메모리를 참조하고 있는 것이 된다.
위 그림은 각 변수들(str1, str2, str3)이 어느 곳에 참조를 했는지에 대한 그림이다.
str1과 str2는 똑같은 string 상수를 가리키고 있으며, str3은 new String()으로 별도의 객체를 생성했기 때문에 heap 영역에도 String Constant Pool과 무관한 메모리 영역을 가리키고 있다.
String Constant Pool은 원래 PermGen(Permanent Generation) 영역에 있었는데, 이 영역은 사이즈가 고정된 메모리 영역이기 때문에 종종 OOM(Out Of Memory)문제가 발생했다고 한다.
그래서 Java 8부터는 Heap 영역으로 위치를 옮기게 되었다.
Heap 영역으로 옮기게 되면서 String Constant Pool 내부의 문자열도 GC의 대상이 될 수 있게 되었다.
출처
https://sabarada.tistory.com/137
https://medium.com/@joongwon/string-%EC%9D%98-%EB%A9%94%EB%AA%A8%EB%A6%AC%EC%97%90-%EB%8C%80%ED%95%9C-%EA%B3%A0%EC%B0%B0-57af94cbb6bc