2019/04/23 - [프로그래밍 노트/JAVA] - [JAVA] String 객체와 리터럴 (메모리관련)
=> 이 글을 읽으면 이해가 더 쉽게 된다.
String 리터럴은 실행할 때 JVM이 특별히 관리를 하게 된다. JVM은 String 리터럴과 불변성에 어떤 도움을 줄까?
클래스가 로드되면 모든 리터럴이 상수 풀(constant pool)
에 위치하게 된다.
그리고 String 리터럴은 풀 안의 같은 상수를 참조해서 이루어지는데 이를 String 인터닝(Interning)이라고 한다.
인터닝은 이 풀 안에 있는 상수들이 JVM에서 실행되는 모든 클래스를 참조할 수 있게 한다.
String 인턴 풀은 컴파일할 때 단지 String 리터럴을 가져오는 것이 아니라, intern 메서드를 이용해서 String 인스턴스를 이풀에 추가한다. (intern 메서드를 사용하게되면, 상수풀에 해당 문자열이 존재하면 상수풀에서 문자열을 가져오고 상수풀에 문자열이 존재하지 않으면 상수풀에 문자열을 추가하고 해당 문자열을 반환한다.)
intern
메서드는 해제에 사용할 수 없다.
String이 힙영역에 저장되어 있지 않더라도 어딘가에는 저장되어야 하는데, 저장되는 장소는 PermGen 영역이다.
수백만 개의 대상이 있는 상수 풀이 있다면 intern 메서드를 많이 사용해야 한다.
각 대상을 찾는데 쏟아붓는 노력으로 인해 애플리케이션의 실행 성능에 영향을 미칠 수 있다.
※ Integer.valueOf(String str) 메서드는 플라이웨이트 패턴으로 구현되어 있다.(String 상수풀도 플라이웨이트 패턴으로 구현되어 있음)
※ -128 ~ 127사이에 있는 값과 관련된 Integer 객체의 같은 인스턴스를 반환하게 된다.
@org.junit.Test
public void intEquality(){
// new String을 명시적으로 호출해서 인스턴스가 다른 메모리 위치에 있게 함
final String str1 = new String("100");
final String str2 = new String("100");
assertFalse(str1 == str2); // 동일성 체크
assertTrue(str1.equals(str2)); // 동등성 체크
final Integer int1 = Integer.valueOf(str1);
final Integer int2 = Integer.valueOf(str2);
assertTrue(int1 == int2);
}
주소값이 다른 두 String 객체 str1, str2를 선언하고 이 값들을 Integer.valueOf()를 사용하여 Integer값으로 변경하였다.
동일성("==")을 체크해보니 true가 나온 것으로 보아 같은 주소값을 참조하는 것을 볼 수 있다.
플라이웨이트 패턴
객체의 내부에서 참조하는 객체를 직접 만드는 것이 아니라, 없다면 만들고, 만들어져 있다면 객체를 공유하는 식으로 객체를 구성하는 방법이다. (상수 풀에 있으면 원하는 정보가 있다면 가져다 쓴다고 생각하면 된다.)
장점
- 많은 객체를 만들때 성능을 향상시킬 수 있다.
- 많은 객체를 만들때 메모리를 줄일 수 있다.
'그 외 ... (정리해야함) > 질문과 답변' 카테고리의 다른 글
오토박싱과 언박싱 이해하기 (0) | 2019.05.02 |
---|---|
타입의 변화는 제네릭에 어떤 영향을 미치는가? (0) | 2019.05.02 |
String 객체의 값을 변경할 수 있는가? (0) | 2019.05.02 |
String은 메모리에 어떻게 저장되는가? (0) | 2019.05.02 |
JAVA에서 다형성과 상속이란 무엇인가? (0) | 2019.05.02 |