- 피드백이나 문의는 댓글 부탁드립니다.
0. 이 글을 작성하기 시작한 이유
회사에서 인턴을 하시는 분이 나에게 질문을 했다.
"JAVA에서 string을 보통 string str = "abc"; 이런 식으로 표현하는데 분명 레퍼런스 타입이면서 new()로 표현을 안 하면 메모리에서 언제 제거될까요? 이 방법이 메모리에 적합한 방법일까요?"
전에 StringBuilder에 대해 간단하게 글을 작성한 적이 있었다.(https://developer-youn.tistory.com/14)
근데 new()로 하는 것과 ""로 하는 것에는 정확히 어떤 차이가 있을까
1. 과거 기억 소환
일단 기억을 더듬어보자.
new 키워드를 통해 객체를 생성하면 heap영역에 할당이 되고 heap 영역에 존재하는 것들은 GC의 대상이 된다.
primitive type(원시 타입)은 stack영역에 쌓이고 닫는 중괄호를 만나게 되면 하나씩 pop되면서 메모리에서 해제된다.
그런데 String은 reference type이면서 String str = "abc"; 이런 식으로 쓸 수 있다. 이 경우에는 어떻게 될까
2. 간단한 결론
(참고로 나는 악필에 그림을 진짜 못 그리는데 파워포인트로 하기 귀찮아서 아이패드로 그려서 올린다.)
결론을 먼저 말하면 거의 위 그림과 유사하게 관리가 된다.(Hotspot jvm기준 계속 위치가 변경되었기 때문이다. 밑에서 추가적으로 설명한다.)
우리가 String을 사용할 때 String str = "abc"; 이런 식으로 ""를 사용해 값을 할당하면 String constant pool에 할당이 된다. 위 방식을 유식하게 말하면 리터럴 방식이라고 한다.
3. 아니 근데 String constant pool의 위치가 계속 바뀌었다.
JAVA7이전에는 Perm영역에 String constant pool이 존재해 리터럴은 gc의 대상이 되지 못했지만 JAVA7부터는 Heap 영역에 존재하기 때문에 참조 카운트가 0이 되면 gc의 대상이 된다.
JAVA7에서는 JAVA Heap 영역에 Permanent 영역이 존재하고 String pool, String constant pool이라 부르는 공간이 들어가 있다.
JAVA8부터는 Permanent 영역이 metaspace 영역으로 바뀌면서 native memory 영역에 들어갔고 JVM이 아닌 OS에 관리가 된다.
4. 추가 정보 (읽으면 좋은 내용)
Perm영역에 존재하던 string constant pool 정보뿐만이 아니라 Class나 Method의 meta data, static object정보, JVM, JIT 관련 데이터가 들어있었다.
이 중에서 Static Object는 Metaspace영역이 아닌 Heap영역으로 옮겨져 최대한 GC의 대상이 되도록 변경되었다.
어쩌다 한 번씩 Collection 객체를 static 하게 구현하여 값을 계속해서 추가하다가 Perm영역이 가득 차 OutOfmemoryerror : permgen space 에러를 볼 수 있다.
다행스럽게도 JAVA8부터는 MaxMetaspaceSize 옵션을 주지 않는 이상 이 문구를 볼 수 없다. perm영역이 metaspace로 바뀌면서 metaspace 영역의 메모리가 부족하다면 자동으로 늘리기 때문이다.
위 이유로 JAVA8부터는 PermSize, PermMaxSize 옵션 대신 MetaspaceSize, MaxMetaspaceSize 옵션을 사용해서 기본값과 최댓값을 설정한다.
이 글에서 부족한 점
- 최신 JVM에 대한 정보
- 내 노력 및 지식
Reference
[1] : https://1-7171771.tistory.com/140
[2] : https://devlog-wjdrbs96.tistory.com/248
[3] : https://mirinae312.github.io/develop/2018/06/04/jvm_memory.html
'JAVA' 카테고리의 다른 글
자바 인터뷰 질문 - 기본기 (1) (0) | 2021.06.17 |
---|---|
JAVA - Garbage Collection (0) | 2021.06.17 |
접근 제어자 (0) | 2021.05.05 |
저는 Eclipse로 개발합니다(1) - debugging (0) | 2021.03.25 |
JVM -XX Options (0) | 2021.03.01 |