정적으로 할당된 메모리 영역으로 기본타입의 데이터가 할당이 되고, Heap 영역에 할당된 Object 타입의 참조를 위한 값들이 Stack 영역에 할당
동적으로 할당된 메모리 영역으로 모든 Object 타입 및 new를 사용하여 객체를 생성하면 힙 영역에 저장
Heap 영역은 Young과 Old 영역으로 설계됨
⇒ 따라서 Young 영역의 수명이 짧은 객체들은 큰 공간을 필요하지 않으며 큰 객체들은 Old 영역에 할당되기 때문에 Old 영역이 Young 영역보다 크게 할당됨
⇒ Young 영역과 Old 영역은 서로 다른 메모리 구조로 되어 있기 때문에 세부적인 동작 방식은 다르나, 기본적으로 가비지 컬렉션이 실행된다고 하면 2가지 공통적인 단계를 따름
가비지 컬렉션을 실행하기 위해 JVM이 프로그램 실행을 멈추는 현상
GC가 실행될 때는 GC를 실행하는 쓰레드를 제외한 모든 쓰레드들의 작업이 중단되고, GC가 완료되면 작업이 재개됨
당연히 모든 쓰레드들의 작업이 중단되면 애플리케이션이 멈추기 때문에, GC의 성능 개선을 위해 튜닝을 한다고 하면 보통 stop-the-world의 시간을 줄이는 작업을 하는 것
또한 JVM에서도 이러한 문제를 해결하기 위해 다양한 실행 옵션을 제공하고 있음
Stop The World를 통해 모든 작업을 중단시키면, GC는 스택의 모든 변수 또는 Reachable 객체를 스캔하면서 각각이 어떤 객체를 참고하고 있는지를 탐색하게 됨
그리고 사용되고 있는 메모리를 식별하는데, 이러한 과정을 Mark라고 함
이후에 Mark가 되지 않은 객체들을 메모리에서 제거하는데, 이러한 과정을 Sweep라고 함
Minor GC는 Eden 영역이 가득차거나, Survivor 영역, old 영역으로 객체를 재배치 할 때 발생하며 실행 속도가 빠름
Major GC는 Old 영역이 가득찬 경우 발생하며 실행 속도가 느림
자바에서 메모리 누수는 더 이상 사용되지 않는 객체들이 GC(가비지 컬렉션)에 의해 소멸되지 않고 누적되는 현상
가비지 컬렉션의 소멸 대상이 되려면 다른 Reference 변수에서 참조하고 있지 않아야 함
public static void main(String[] args) throws Exception {
List<Integer> li = new ArrayList<>();
for (int idx=1; true; idx++) {
if (idx % 100 == 0) {
li = new ArrayList<>();
Thread.sleep(100);
}
for(int k = 0; k < 100; k++){
li.add(k);
}
System.out.println("idx : "+ idx);
}
}
public static void main(String[] args) throws Exception {
List<Integer> li = new ArrayList<>();
for (int idx=1; true; idx++) {
if (idx % 100 == 0) {
// li = new ArrayList<>();
Thread.sleep(100);
}
for(int k = 0; k < 100; k++){
li.add(k);
}
System.out.println("idx : "+ idx);
}
}