본문 바로가기

Language/Java

Java String interm

String.intern()


String클랫의 intern()은 String인스턴스의 문자열을 'constant pool'에 등록한다.

'constant pool'에 이미 존재할 경우에는 해당 문자열의 주소를 반환한다.

------------------------------------------------------
String s1 = "AAA";
String s2 = new String("AAA");
s2 = s2.intern();
------------------------------------------------------

s2에는 s1과 같은 주소값이 저장되게 된다(기존의 s2의 인스턴스는 가비지 컬렉트 된다)

intern은 Heap에 만들어진 객체를 놓아주고, String pool에 있는 객체를 가리키게 합니다.
그렇게 됨으로써 Heap의 메모리를 아낄 수 있습니다.

하지만 intern() 메소드를 사용함으로 인해서 손해를 보는것도 생각해 보아야 합니다.

1. 우선 String 객체를 하나 만들어야 합니다.
2. String의 equals 메소드를 이용해서 String pool에 있는 놈을 찾아서 비교 ( 시간이 걸림 )
3. String pool에 들어 갔으므로, 더 이상 GC(가비지컬렉션)의 대상이 될 수 없습니다. ( 메모리 관리 불가 )


시간이 얼마나 걸리는지 간단한 예제를 가지고 테스트 해보도록 하면 아래의 결과를 얻을 수 있습니다.

  long startTime = System.currentTimeMillis();
  for ( int i = 0 ; i < 5000000; i++ ) {
       String str = "Hello";
  }
  long endTime = System.currentTimeMillis();
  System.err.println("String pool = "  + ( endTime - startTime));
  
  long startTime1 = System.currentTimeMillis();
  for ( int i = 0 ; i < 5000000; i++ ) {
       new String("Hello");
  }
  long endTime1 = System.currentTimeMillis();
  System.err.println("new String = "  + ( endTime1 - startTime1));
  
  long startTime2 = System.currentTimeMillis();
  for ( int i = 0 ; i < 5000000; i++ ) {
       new String("Hello").intern();
  }
  long endTime2 = System.currentTimeMillis();
  System.err.println("new String intern = "  + ( endTime2 - startTime2));


결과
String pool = 31
new String = 188
new String intern = 1796


intern을 하게 되면, new String하는 시간과 String pool을 뒤지면서 equals하는 시간까지 걸리므로
당연히 그 속도가 느릴 수 밖에 없습니다.

그리고
보통 intern()의 특징인 "메모리를 아낄 수 있다" 만 생각을 하고 프로그래밍을 하지,
intern()하는데 시간이 오래 걸린다와, GC의 대상이 될 수 없다. 라는것은 생각하지 않고 프로그래밍을 하지요.

특히, "메모리를 아낄 수 있다" 라는 생각에 10번도 안쓰는 String 객체를 intern()을 이용해서 상수화 시키게 되면,
영원히 GC의 대상이 되지 않기 때문에 오히려 "메모리를 버리는 꼴"이 되는것을 조심해야 합니다.

똑같은 문자열을 가지는 String을 100개를 생성한다고 해도, 나중에 GC가 되어서
메모리에서 사라질 가능성이 있다면, 오히려 그것이 메모리를 아낄 수 있는 길입니다.


결론.
intern을 제대로 이해하지 못하고 사용한다면
메모리를 아끼는것이 아니라, 메모리를 마음껏 버리는 짓을 하게 될 것입니다.


- 내용추가(2013.10.23)
생각해 보니 String.intern()된 애들도 GC의 대상에 포함될 수 있을 듯 합니다.
CustomClassLoader를 만든뒤에 Class를 loading했을때, CustomClassLoader가 GC가 되면class자체에 대한 reference도 없어 질테니, class에 설정된 String들도 GC의 대상이 될 가능성이 있겠네요.



'Language > Java' 카테고리의 다른 글

Java arraycopy [Java 배열 복사]  (0) 2014.02.27
JAVA NIO(non-blocking I/O)  (0) 2014.02.27
OXM(Object XML Mapping) [XML 바인딩 기술들...]  (0) 2014.02.27
Java Doc  (0) 2014.02.27
Java에서 직렬화(Serializable)가 불가능한 경우  (0) 2014.02.27