2014년 10월 20일

자바코드에서 "abcd" 과 new String("abcd") 차이 ?

아래의 코드1를 보자

코드1
String x = "abcd";
String y = "abcd";

System.out.println( x == y);       // true 출력
System.out.println( x.equals(y) ); // true 출력
 
코드1과 같이 쌍따옴표를 사용하여 만들어진 문자열을 String literal 라고 부르고, 이들은 String Pool 이라고 불리우는 곳에 저장된다.

동일한 String literal 이 한번 이상 만들어 지면, 하나의 복사본만이 String Pool  저장되는데, 이것을 "interning" 이라고 부른다. 자바는 컴파일 과정에서 자동으로 interning 처리한다.

코드2


String a = new String("abcd");
String b = new String("abcd");

System.out.println( a == b);       // false 출력
System.out.println( a.equals(b) ); // true 출력

a == b 가 참이 아닌것은 a와 b가 힙 메모리에 다른 객체를 참조하고 있어서다.




문자열은 프로그램 개발시에 가장 빈번하게 사용되지만, 그 비용이 적지 않아, 초기 자바 디자이너들이 성능을 고려하여 이와 같은 캐쉬를 고안한것 같다.

코드에서 x == y 가 참인것은, x 와 y 가 Method Area (runtime constant pool, field, 그리고 method 데이터들과 생성자 코드가 저장된는 공간)에 위치한 String Pool 에 동일한 문자열을 참조하고 있기 때문이다.

String literal과 메모리
초기의 자바에서(~ 1.6) String Pool 은 Heap 메모리의 PermGen 에 위치하고 있었다. PermGen 은 아주 제한된 공간으로, 기본 크기가 64 MB(JVM 버전에 따라 차이가 있음) 이고 클래스로더에의하여 로드된 클래스, String Pool 등이 저장된다. 이러한 공간적 제안으로 너무 많은  String literal 또는 interning 은 PermGen 공간에 대한 OutOfMemory 를 발생시켰다.

오라클의 엔지니어들은 자바 1.7 에서 string pool 의 위치를 heap 으로 배치하는 아주 중요한 변화를 만들었다. 즉 더이상 제안된 PermGen 공간의 크기 때문에  OutOfMemory 을 걱정하지 않아도 된다는 것이다.




참고자료
Create Java String Using ” ” or Constructor?
String.intern in Java 6, 7 and 8 – string pooling
Difference between String literal and New String object in Java


댓글 2개: