JVM의 Memory 할당 방식 : Stack과 Heap Memory가 동작하는 방법

2022. 1. 30. 23:12· Machine/JVM
목차
  1. JVM의 메모리 할당 방식
  2. 메모리 할당 예제
  3. JVM의 Stack과 Heap
  4. Stack에 저장되는 방식
  5. Heap에 저장되는 방식
  6. Heap의 한계점
  7. 정리
반응형

JVM의 메모리 할당 방식

JVM은 기본적으로 Stack Memory 와 Heap Memory 라 불리는 두가지 저장 공간을 이용해 메모리를 할당한다. 이들에 메모리를 할당하는 방법은 바이트 코드를 한 줄 한 줄 읽는 것이다. 한 줄 한 줄 읽혀진 값들은 JVM의 Stack 영역에 차곡차곡 

 

 

메모리 할당 예제

예를 들어 다음과 같은 코드가 있다고 해보자.

fun main() {
    val numberA = 12
    val numberB = 15
    val numberC = numberA + numberB
}

fun add(numberA: Int, numberB: Int): Int {
    return numberA + numberB
}

 

위 코드에서 main function이 수행되면 다음과 같은 과정을 거쳐 메모리가 할당된다.

1. numberA를 읽는다

그림1. 과정1

 

2. numberB를 읽는다.

그림2. 과정2

 

3. number1에 numberA값인 12를 할당한다, number2에 numberB의 값인 15를 할당한다.

그림3. 과정3

 

4. temp 값을 생성하여 number1 + number2를 한 값을 할당한다.

그림4. 과정4

 

5. temp에 저장된 값을 numberC에 할당한 후 return하면 add function과 관련된 모든 값들이 사라진다.

그림5. 과정5

 

6. main function이 끝났으므로 모두 지워진다.

그림6. 과정6

 

 

 

JVM의 Stack과 Heap

 

위의 과정을 통해 우리가 작성한 코드들이 어떻게 메모리에 올라가는지 살펴보았다. 기본적으로 코드들은 한 줄 한 줄 읽혀서 Stack이라 불리는 공간에 차곡차곡 쌓인다. 마지막에 들어온 변수가 먼저 나간다고 해서 LIFO(Last In First Out) 구조를 가진다고도 한다. 하지만, 모든 변수를 Stack에 저장할 수 있는 것은 아니다. 간단한 변수인 Primitive Type의 변수들은 Stack에 저장이 가능하지만, 복잡한 변수는 Heap 공간에 저장되고 Stack에는 해당 Heap 공간을 가리키는 변수가 저장된다.

 

정리하면 한 줄을 읽었을 때 변수가 있다면 무조건 Stack에 저장되는데, 데이터도 Stack에 저장되는 경우는 간단한 데이터인 경우이며, 조금만 복잡해지더라도 Stack에는 변수의 주소값만 저장되고 실제 데이터는 Heap 영역에 저장된다.

 

예를 들어 다음과 같은 main function이 수행되었다고 해보자. 

fun main() {
    val number = 12
    val myData = MyData(15)
}

class MyData(val data : Int)

 

이때 MyData는 클래스이므로 복잡한 데이터이다. 따라서 다음과 같이 저장된다.

 

 

그림7. Heap에 저장되는 방식

 

 

Stack에 저장되는 방식

JVM의 Stack에는 Primitive 타입의 변수들만이 저장된다. Java를 기준으로는 int, boolean 등과 같은 Primitive 타입의 변수들이 저장되며, 이들을 Boxing 한 Integer, Boolean과 같은 Reference 타입의 변수는 저장하지 못한다. Kotlin을 기준으로는 이것에 대해 생각할 필요가 없다. Int나 Boolean 타입을 쓰면 Kotlin 바이트코드 컴파일러가 Primitive이 들어갈 수 있는 곳에는 Primitive 타입으로 최적화시켜서 저장시켜주며, Primitive 타입을 쓸 수 없는 경우에는 Reference 타입의 변수로 저장해준다.

 

Heap에 저장되는 방식

JVM의 Heap에는 복잡한 타입의 변수 클래스 타입, Interface 타입, ArrayType의 변수들이 저장된다. 복잡한 데이터여서 Heap 내부에 Heap를 Reference한다면 Heap의 데이터가 다시 Heap의 데이터를 참조할 수도 있다.

 

예를 들어 아래와 같이 Array내부에 MyData가 두 개 있는 경우를 살펴보자.

fun main() {
    val myDataArray = arrayOf(MyData(1), MyData(2)
}

class MyData(val data : Int)

 

그러면 Stack에서 myDataArray는 Heap의 Array<MyData>를 가리키고, 이 Array에는 주소값이 2개 있어서 각 주소값은 MyData(1)과 MyData(2)를 가리킨다.

그림8. Array 내부에 복잡한 데이터가 있는 경우

 

 

Heap의 한계점

Stack은 좁은 메모리 공간이지만, Heap은 넓은 메모리 공간이다. Stack 메모리에 값을 할당하고 해제하는 것은 많은 비용이 들지 않지만, Heap 메모리에 값을 할당하고 해제하는 것은 많은 비용을 요한다. 따라서 너무 Heap에 데이터를 자주 할당하고 해제하는 방식으로 코드를 짠다면 같은 방식을 Stack에 했을 때보다 수십배의 속도 차이가 날 수 있다. 이 점을 유의하면서 Heap을 사용할 때는 이 점을 유의해서 코드를 짜도록 하자.

 

 

정리

즉, Stack에는 정말 간단한 변수나 Heap을 가리키는 주소값 둘 중 하나만 저장된다. 만약 Heap에 저장되는 변수에 복잡한 데이터가 있을 경우에는 Heap 데이터 내부에 Heap의 메모리 공간을 가리키는 변수가 저장된다. 

반응형
저작자표시 비영리 변경금지
  1. JVM의 메모리 할당 방식
  2. 메모리 할당 예제
  3. JVM의 Stack과 Heap
  4. Stack에 저장되는 방식
  5. Heap에 저장되는 방식
  6. Heap의 한계점
  7. 정리


 

Kotlin, Android, Spring 사용자 오픈 카톡

오셔서 궁금한 점을 질문해보세요!
비밀번호 : kotlin22

open.kakao.com

'Machine/JVM' 카테고리의 다른 글
  • JVM에서 Garbage Collection(GC) 이 일어나는 방식 알아보기
  • JConsole을 활용한 Java Process Code Cache 모니터링
  • 코드 캐시(Code Cache) 사이즈 조정을 통한 JVM 최적화
  • JVM의 JIT(Just In Time Compilation) 컴파일이란? C1, C2 컴파일러를 이용한 최적화
Dev.Cho
Dev.Cho
'조세영의 Kotlin World'는 Kotlin를 전문적으로 다루는 개인 기술 블로그입니다. Kotlin 세계에 대한 양질의 자료를 제공하며 Kotlin, Android, Spring, CI, CD 분야에 대해 다룹니다.
Dev.Cho
조세영의 Kotlin World
Dev.Cho
전체
오늘
어제

블로그 메뉴

  • LinkedIn
  • GitHub
  • 분류 전체보기 (491)
    • Kotlin (104)
      • Class and Interface (19)
      • Variable and Function (8)
      • Modifier (5)
      • Collection (14)
      • Time (8)
      • 동시성 제어 (7)
      • Reactive Programming (2)
      • Paradigm (2)
      • Kotlin 자료구조 (15)
      • Design Patterns (11)
      • Algorithm (3)
      • Exception (1)
      • 기타 (9)
      • Update History (0)
    • Coroutines (32)
      • Coroutine Basics (18)
      • Flow (9)
      • CoroutineScope (3)
      • Debugging (2)
    • Testing Codes (28)
      • Test 기본 (3)
      • JUnit5 (9)
      • MockK (6)
      • Testing Coroutines (1)
      • Testing Android (8)
      • Test 기타 (1)
    • Spring (50)
      • Dependency Injection (18)
      • Settings (5)
      • REST API (0)
      • DevTools (1)
      • MVC (18)
      • Error (2)
      • MongoDB (2)
      • Database (4)
    • Android (39)
      • Architecture (2)
      • Component (5)
      • Manifest (1)
      • Lifecycle (2)
      • Dependency Injection (17)
      • Resource (1)
      • Storage (1)
      • Security and Optimization (1)
      • WebView (2)
      • Error (6)
    • Android Jetpack Compose (33)
      • Compose (6)
      • Compose Modifier (13)
      • Compose Resource (4)
      • Compose State (4)
      • Compose Side Effect (6)
    • Android Jetpack Compose UI (48)
      • Compose Layout (14)
      • Compose Text (10)
      • Compose Button (5)
      • Compose Dialog (2)
      • Compose TextField (0)
      • Compose UIs (4)
      • Compose Animation (1)
      • Compose Canvas (12)
    • Android Jetpack (10)
      • Datastore (5)
      • ViewModel (4)
      • LiveData (1)
      • Paging (0)
    • KMP (5)
    • Programming (4)
    • Machine (9)
      • JVM (7)
      • Linux (2)
    • CI, CD (74)
      • Gradle (12)
      • Groovy Gradle (5)
      • Git (25)
      • Git Remote (5)
      • GitHub (5)
      • GitHub Actions (21)
    • Network (33)
      • GraphQL (12)
      • HTTP (11)
      • Basic (9)
    • 오픈소스 (3)
    • Database (3)
      • MongoDB (3)
    • IDE (6)
      • Android Studio (2)
      • Intellij (4)
    • Firebase (1)
    • Javascript (9)

공지사항

  • 코틀린 코루틴 완전 정복 강의 in 인프런 오픈
  • 코틀린 코루틴의 정석 책 출간
  • Kotlin Coroutines 공식 기술 문서 한국어 번⋯
  • GitHub에서 조세영의 Kotlin World를 Foll⋯
  • 문의&제안

인기 글

태그

  • dagger2
  • Spring boot
  • java
  • github
  • junit
  • Dependency Injection
  • compose
  • 안드로이드
  • 스프링
  • Android
  • GIT
  • GraphQL
  • 의존성 주입
  • kotlin spring
  • 코루틴
  • junit5
  • HTTP
  • 코틀린
  • Unit Testing
  • Jetpack Compose
  • github actions
  • Spring
  • Coroutine
  • flow
  • junit4
  • Kotlin
  • gradle
  • Class
  • 유닛 테스팅
  • Android Compose

최근 글

반응형
hELLO · Designed By 정상우.v4.3.0
Dev.Cho
JVM의 Memory 할당 방식 : Stack과 Heap Memory가 동작하는 방법
상단으로

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.