컴퓨터 상식

가상메모리에도 불구하고 OOM(OutOfMemory)이 발생하는 이유

우리로 2020. 11. 11. 16:25

프로그램을 실행할 때 모든 영역이 다 필요한 건 아니다. PC(Program Counter)가 가리키는 부분과 관련된 데이터, 힙, 스택영역이 필요하기 때문에 OS는 가상메모리 라는 걸 활용한다.

 

가상메모리 = Main Memory + Hard Disk

 

즉 필요없는 부분은 하드디스크에 뒀다가 필요할 때 부른다.

 

이 과정을 Page Swapping 이라고 부른다.

 

프로세스의 모든 영역이 Swap의 대상이므로 Heap과 Stack 영역도 그로부터 자유롭지 못하다.

 

여기서 드는 의문

 

그러면 OOM(Out of Memory)은 왜 발생하지?

 

이 에러는 할당된 범위를 넘어선 영역에 대해서 메모리 할당을 요구할 때 발생한다. 보통 Runtime 때 Heap 영역에서 발생한다. 

 

Heap을 Swapping 하면 계속 할당할 수 있지않을까? 하는 의문이 들었는데, 여러가지 문제가 있다.

 

1. 하드웨어 한계

- 32bit CPU는 4GB까지의 주소만 사용할 수 있다. 이 범위를 넘어서면 OutOfMemory다.

- 64bit CPU이지만 RAM이 4GB이면 4GB까지만 할당할 수 있다. 이 범위를 넘어서면 OutOfMemory이다.

 

2. 소프트웨어적인 한계

- JVM 같은 Machine에서 한계를 정해놨을 수도 있다.

 

예를 들어서

 

이런 식으로 되어있으면 Xms1990m 설정은 이 JVM은 1990M을 최대 힙 사이즈로 쓰겠다는 뜻이다.

1990M = 2,086,666,240 Byte 이다.

 

테스트를 하면 이런 모양이 된다. 

 

532254060 개의 Integer는 2,129,016,240 Byte이다.

 

최대 힙 크기를 넘어서기때문에 다소 의아하지만 내 추측으로는

 

1) ArrayList는 배열이 꽉 찰때마다 이전 크기의 두 배인 배열을 할당한다. 그리고 "Logical Space"는 실제로 변수가 할당될 때 물리 메모리와 Mapping된다. 그래서 미리 배열을 할당한 크기가 532,254,060이고, 이 배열에 원소를 하나씩 넣어가는 과정에서 OOM이 발생했다. 그 결과 ArrayList의 크기가 최대 Heap을 넘어가게 됐다.(Size는 ArrayList의 헤더에 이미 입력되어있으므로)

 

이다.