일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 기본 Manifest 속성이 없습니다
- springboot jwt example
- String Constants Pool
- JPA
- jvm 모델
- spring filter ordering
- jvm memory model
- jpa pagination
- JWT
- springboot maven plugin
- jvm memory structure
- String Pool
- string comparison
- spring jwt
- install mongodb docker
- jvm 메모리 구조
- Constants pool
- docker mongodb install
- filter ordering
- HHH000104
- springboot jwt
- springboot mongodb config
- jwt example
- springboot-angular-jwt
- angular jwt
- spring-boot-maven-plugin
- docker mongodb
- mongodb install ec2
- intern
- jwt token
- Today
- Total
개발블로그
String Constants Pool 본문
Primitive type value를 비교할 때에는 주소 값을 비교하기 위해 '==' 연산자를, Reference type value를 비교할 때에는 실제 참조하는 값을 비교하기 위해 'equals' 메소드를 이용합니다. 그리고 String type value를 비교할 때에는 'equals'를 이용하기를 권장하는데, '==' 연산자로 비교하면 어떻게 될까요?
String str1 = "SYS4U";
String str2 = "SYS4U";
System.out.println(str1 == str2); //true
System.out.println(str1.equals(str2)); //true
(literal 방식으로 String을 생성한다면) '==' 연산자를 이용해도 결과가 일치합니다. '==' 연산자를 이용했을 때 true가 나온다는 것은 주소 값이 같다는 의미인데, 어떻게 된 일일까요?
이번 장에서는 이 의문을 풀기 위해 String type의 변수가 메모리에 어떻게 적재되는지 알아보겠습니다.
String은 Reference type 변수처럼 Heap 영역에 저장되는데, 그 중에서도 'String Constants Pool'이라는 곳에 저장이 됩니다.
위 코드의 1라인이 실행되면 str1이라는 Reference type 변수가 만들어지고, 실제 값 "SYS4U"는 Pool에 저장됩니다.
2라인에서는 저장할 값인 "SYS4U"가 이미 Pool에 있으므로 Reference type 변수 str2가 기존의 "SYS4U"를 참조하여, Pool에 있는 값을 재사용합니다.
따라서 str1과 str2는 같은 주소 값을 가지므로 '==' 연산자로 비교했을 때, true가 리턴된 것입니다.
그러나 실제로 프로그램을 작성할 때, String type 변수를 '==' 연산자로 비교해서는 안됩니다. literal 방식으로 생성한 String type은 String Constants Pool에 적재되지만, 비교할 대상들을 직접 literal 방식으로 생성하지 않았다면 String Constants Pool에 적재되어 있다는 것을 확신할 수 없습니다. 따라서 equals 연산자로 비교하는 것을 권장합니다.
이번에는 다른 방식으로 String 변수를 정의해보겠습니다.
String str3 = new String("SYS4U"); //생성자 방식
String str4 = "SYS4U"; //literal 방식
System.out.println(str3 == str4); //false
System.out.println(str3.equals(str4)); //true
4라인을 통해 str3과 str4의 주소 값이 다르다는 것을 확인할 수 있습니다. 이는 생성자 방식과 literal 방식의 동작 방식이 다르기 때문입니다.
String을 생성자 방식으로 생성하면 Pool에서 재활용하지 않고 다른 Reference type 변수처럼 Heap Area에 새로운 메모리를 할당받습니다.
따라서 str3과 str4의 주소 값이 달랐던 것입니다.
그러나 String을 literal 방식으로 생성하면, 내부적으로 new String("").intern() 을 호출합니다. intern 메소드가 Pool을 검색하여, Pool에 있는 문자열이면 해당 주소 값을 반환해주고 그렇지 않으면 Pool에 새롭게 할당한 주소 값을 반환해줍니다.
이전 장에서 언급했다시피, java 8을 기점으로 Constants Pool의 위치가 Method Area의 Perm에서 Heap area의 metaspace 영역으로 이동되었습니다. 그 이유는 Perm 영역의 크기를 Runtime시에 조정할 수 없어, OutOfMemory가 발생하는 경우가 있었기 때문입니다. Heap area로 이동하게 되면서 literal로 생성한 모든 문자열이 GC의 대상이 되었고, 따라서 OOM을 일부 방어할 수 있게 되었습니다.
'Java' 카테고리의 다른 글
JVM Memory Model (Runtime Data Areas) (0) | 2019.08.22 |
---|