런타임 데이터 영역

pc(program counter) 레지스터

  • cpu 내 기억장치인 레지스터를 지칭하는 것이 아니다.
  • Java는 플랫폼에 독립적으로 동작하기 위해 CPU에서 직접 instruction을 수행하지 않는다.
  • 대신 pc 레지스터라는 별도의 메모리공간를 두고 이를 이용해 instruction을 수행한다.
  • pc 레지스터에는 현재 실행중인 JVM instruction이 저장된다. 네이티브 메서드의 경우는 JVM에서 실행되지 않으므로 undefined값을 가지게 된다.
  • 스레드 마다 pc 레지스터를 가진다.

스택

  • 스레드마다 스택을 가진다. 다른 스레드의 스택영역엔 접근 할 수 없다.
  • 메서드가 호출될 때 마다 스택에 새로운 프레임들이 생성되고 메서드 종료 시 스택에서 제거된다.
  • 스택은 고정사이즈일 수도 있고 동적으로 사이즈를 확장할 수도 있다.
  • 스택의 메모리 부족과 관련된 두가지 종류의 에러가 있다.
    • StackOverflowError - 고정 사이즈의 스택에서 지정된 사이즈를 초과할 경우 발생
    • OutOfMemoryError - 다이나믹 사이즈 스택에서 메모리가 부족할 경우 발생

  • 모든 스레드가 접근할 수 있다.
  • 프리미티브 타입이 아닌 데이터들이 저장되는 영역이다. 클래스 인스턴스, 배열 등이 포함된다. 메모리 관리에 대한 스펙은 규정되어있지 않고 벤더사가 알아서 구현하도록 되어있다.
  • 힙 영역 메모리은 인접해있지 않아도 된다. 힙 영역이 부족해지만 OutOfMemoryError가 발생한다.

메서드 영역(Method Area)

  • 모든 스레드가 접근할 수 있다.
  • 코드들이 저장된다고 볼 수 있다.
  • 클래스의 런다임상수풀, 필드, 메서드 데이타, 메서드 코드, 생성자와 같은 것들을 저장한다.
  • JVM의 시작될 때 같이 생성된다. 논리적으론 힙에 속하지만 가비지 컬렉션을 한다던가 하는 건 벤더사에 맡기고 있다.
  • 고정사이드 혹은 런타임에 확장 가능한 사이즈를 갖기도 한다.
  • 이 영역의 메모리가 부족해지만 OutOfMemoryError가 발생한다.

보충자료

프레임이란?

  • 메서드가 호출될 때 마다 새로운 프레임이 생성된다. 메서드 종료 시 스택에서 제거되며 리턴값을 이전 프레임에게 전달한다.
  • 다이나믹 링킹, 메서드 리턴값, 디스패치 익셉션과 같은 데이터를 저장하기 위해 사용된다.
  • 프레임은 아래와 같이 구성된다.
    • 로컬 변수
      메서드의 지역변수를 배열 형태로 저장한다. 프리미티브 타입의 값은 스택에 같이 저장되고, 레퍼런스 타입은 실제 값은 힙영역에 있고 그 힙영역의 주소값을 스택에 저장한다.
    • 오퍼랜드(Operand) 스택
      계산을 위한 입출력 데이터를 저장하는 공간이다.
    • 런타임상수풀(Run-time constant pool) 레퍼런스
      프레임마다 런타임상수풀(Run-time constant poo) 레퍼런스를 포함하고 있다. 심볼릭 링크 형태의 메서드/변수를 참조하는 경우 런타임상수풀을 참조하여 실제 로드된 스트럭처의 오프셋 형태로 변환한다. 런타임상수풀을 사용함으로써 동적 로딩이 가능해진다.

프레임의 로컬 변수와 오퍼랜드 예제

public int add(int a, int b) {
    int c = a + b;
  return c;
}

이 코드의 바이트 코드는 다음과 같다

Code:
  stack=2, locals=4, args_size=3
    0: iload_1 # 지역변수 1번을 오퍼랜드 스택에 입력(Push)
    1: iload_2 # 지역변수 2번을 오퍼랜드 스택에 입력
    2: iadd # 오퍼랜드 스택에서 두 꺼내어(Pop)을 꺼내어 더 한뒤 그 결과를 오퍼랜드 스택에 입력
    3: istore_3 # 결과를 c에 저장
    4: iload_3 # 리턴 값 꺼내기
    5: ireturn # 리턴
  LocalVariableTable:
      Start  Length  Slot  Name   Signature
      0       6     0    this   LMyMain;
      0       6     1       a   I
      0       6     2       b   I
      4       2     3       c   I


여기서 a = 50, b = 20이라고 하면

출처 : Geeksforgeeks

마지막 ireturn을 실행하면 이전 프레임에게 결과값을 리턴하고 해당 프레임은 소멸된다.

참고자료

https://www.holaxprogramming.com/2013/07/16/java-jvm-runtime-data-area/
https://heowc.tistory.com/53
https://johngrib.github.io/wiki/jvm-stack/

+ Recent posts