String.intern에 설명에 앞서 다음 퀴즈를 한번 보자.

 

전제조건) String string = “test”;

전제조건) String test = “test”;

Q1) test == “test”  ?

Q2) test == new String(“test”) ?

위 문제의 답(java 1.6+에서)은 각각 true, false 이다.

 

왜 그럴까?

위 문제의 답을 알기 위해서는 intern이 뭘 하는지에 대해서 알아야 한다.

사실 위와 같은 답이 나온 이유는 일단 컴파일러가 점점 똑똑해져서 사용자가 의도를 해하지 않는 범위 내에서 최적화 작업을 하기 때문입니다. 위 코드에서 컴파일러가 최적화를 위해 해주는 작업은 Q1의 “test”를 new String(“test”).intern()으로 바꾸어 주는 것입니다. 더 정확히 표현하면 코드상에서 스트링 익스프레션으로 선언된 스트링을 자동으로 String.intern으로 바꾸어 주는 것입니다.

그럼 왜 String.intern()이 어떤 일을 하길래 최적화라는 명목 아래 알아서 변환 작업을 해주는 걸까?

JVM에는 String을 저장해두는 String pool 이라는 것이 있는데, 이 녀석은 String이 너무 많이 로딩될 경우 OME가 발생할 여지가 있기 때문에 동일한 값(char 배열)을 갖는 경우에는 String pool에서 받아오게 한다. 이렇게 해서 같은 값을 갖고 있지만 다른 메모리를 차지하는 String을 줄여서 메모리를 보다 효율적으로 사용하게 된다. (intern으로 선언할 경우 String pool에 캐쉬되지만 이를 직접 참조하는 값이 없을 경우에는 gc된다.)

자 그럼  왜 Q1은 true를 리턴하는지 설명이 가능하다. “test”로 선언할 경우 새로운 메모리를 할당해서 생성될거라 예상 하지만 intern을 통해서 String pool에 캐쉬되어 있는 String을 리턴한다. 그렇기 때문에 동일한 주소값을 갖는 객체를 비교하기 때문에 true를 리턴한다. 역으로 Q2에서는 new를 통해 새로운 메모리를 할당해서 생성되기 때문에 비교 값이 false를 리턴하게 된다.

개인적으로는 메모리 사용이 정말 중요한 embeded 프로그램 등에서는 intern의 사용이 고려될 수 있겠지만, 웹 애플리케이션 등을 개발할 경우에는 고려할 필요가 없다고 생각한다.

미비한 성능향상 보다는 가독성 높은 코드가 더 값지다고 생각하기 때문이다.