JVM과 자바 메모리 구조

3 분 소요

1. JVM의 특징

  1. 플랫폼에 독립
    운영체제와 무관하게 가상머신 위에서 동작함. 가상머신은 스팩이 정해져있고 구현은 OS마다 다르다.

  2. stack 기반
    대표적인 컴퓨터 아키텍처인 인텔 x86, ARM과 같은 하드웨어가 레지스터 기반으로 동작하는데 JVM은 스택 기반으로 동작한다.

  3. Garbage Collection
    메모리 정리를 알아서 한다.

2. 자바 실행 과정

자바 실행 과정

2.1. 실행 과정

  1. 자바 컴파일러를 통해 .java 파일을 바이트코드로 된 .class 파일로 컴파일

  2. Class Loader에 의해서 class 파일들이 JVM의 메모리에 로딩됨. 메서드나 클래스 변수들은 이 때 적절한 메모리 영역에 배치된다.

  3. 로딩된 class 파일은 Execution Engine을 통해 해석됨.

  4. 해석된 프로그램은 Rumtime Data Areas에 배치되어 실질적인 수행이 이루어짐. 즉, main 메서드를 찾아 순차적으로 실행하면서 지역변수, 참조변수 등을 스택에 쌓는다.

  5. 실행 중 JVM은 필요에 따라 Thread Synchronization과 Garbage Collection같은 관리작업을 수행함.

2.2. Class Loader

컴파일된 class 파일을 JVM의 메모리에 로딩한다. (런타임시에 동적으로 로딩함)

2.3. Execution Engine

Class Loader를 통해 JVM내의 데이터 영역에 배치된 바이트코드를 실행한다. Execution Engine은 자바 바이트코드를 명령어 단위로 읽어 실행한다.

2.4. Runtime Data Area

JVM도 일종의 프로그램으로 운영체제 위에서 실행되면서 할당받는 메모리 영역이다. 총 5개의 영역으로 나눌 수 있다.

메모리

위 그림이 정확히 맞는지 모르겠다. 그림에는 Heap에 Permanent Generation 영역이 있는데 다른 글을 보니 Permanent 영역의 역할이 Method Area와 동일했다. 그래서 또 찾아보니 Permanent 영역의 subset이 Method Area라고 하고 Heap에 포함된 영역이 아니라 별개 영역으로 표시하였다. JVM따라서 다른건지 정확히 잘 모르겠다.

2.4.1. Method(Static) Area

  • 모든 Thread가 공유하는 영역으로 JVM이 시작될 때 생성되어 프로그램 종료까지 유지됨.
  • 로딩된 Class와 Interface에 대한 Runtime Constant Pool, 멤버 변수, static 변수, 메서드와 생성자의 바이트코드 등을 저장한다.
    (로딩된 클래스의 정보를 저장한다는 의미이다. static 변수는 class 정보라 이곳에 저장되고 일반 멤버 변수는 실제 객체가 생성될때 heap 영역에 할당되어 저장된다. )
  • 구성 방식이나 GC방법은 JVM 벤더마다 다를 수 있다.
(참고) Rumtime Constant Pool
  • Method Area에 포함되지만 독자적인 중요성이 있다.
  • Class와 Interface의 상수, 멤버필드, 메서드에 대한 모든 레퍼런스를 저장한다.
  • JVM은 Runtime Constant Pool을 통해 해당 메서드나 멤버 필드의 메모리 상 주소를 찾아 참조한다.

2.4.2. Heap Area

  • instance(객체)나 배열을 저장하는 공간으로 런타임시에 동적으로 할당하여 사용된다.
  • Heap 영역에 생성된 객체나 배열은 Stack 영역의 변수나 다른 객체의 필드에서 참조한다.
  • 객체가 참조되지 않는 경우 GC 대상이 된다.
  • 구성 방식이나 GC방법은 JVM 벤더마다 다를 수 있다.
  • Method Area와 마찬가지로 모든 Thread에서 공유하는 영역

2.4.3. Stack Area

  • Thread 마다 하나씩 존재하며 Thread가 시작될 때 할당된다.
  • Stack Frame이라는 구조체를 저장하는 Stack으로 Frame은 메서드 호출에 대한 수행정보(메서드 정보, 지역변수, 매개변수)를 가지고 있다.
  • 지역변수나 매개변수가 Primitive 타입인 경우 Stack 영역에 직접 저장한다.
  • Reference 타입 변수일 경우에는 Heap Area나 Method Area에 있는 값을 참조한다.
  • 정리하면 메서드를 호출할 때마다 해당 메서드가 동작할때 필요한 정보들을 보고 Stack Frame을 만든 뒤 추가(push)하고 메서드가 종료되면 해당 Frame을 제거(pop)하는 동작을 수행한다.
  • Exception 발생 시 printStackTrace() 등의 메서드가 보여주는 Stack Trace 정보의 각 라인은 Stack Frame을 표현한 것이다.

2.4.4. PC(Program Counter) register

  • Thread 마다 하나씩 존재하며 Thread가 시작될 때 생성된다.
  • 현재 수행 중인 JVM 명령 주소를 갖는다.

2.4.5. Native Method stack

  • 자바 외 언어로 작성된 Native 코드를 위한 Stack이다.
  • 자바는 java외의 언어로 작성된 프로그램과 연동할 수 있도록 하기 위해 JNI(Java Native Interface) 표준 규약을 제공한다.
  • 즉, Native Code로 작성된 함수 호출을 Java 프로그램에서 직접 수행할 수 있는데 이 때 함수의 매개변수 지역변수 등을 바이트 코드로 저장한다.

2.5. 객체 생성과 메모리 예

public class Exam {
    int c, d;
    public int add(int a, int b) {
        c = a + b;
        return c;
    }
    public int multi(int a, int b) {
        d = a * b;
        return d;
    }
}

public class MemoryTest2 {
    public static void main(String[] args) {
        int sum, multi;
        int x, y;
        x = Integer.parseInt(args[0]);
        y = Integer.parseInt(args[1]);  // 1번
        Exam obj1 = new Exam();
        Exam obj2 = new Exam();         // 2번
        sum = obj1.add(x, y);
        multi = obj2.multi(x, y);
        System.out.println("add = " + sum);
        System.out.println("multipy = " + multi);
    }
}
  1. main() 메서드 실행
    실행과 메모리1

  2. Exam 객체의 생성
    실행과 메모리2

  3. Exam 객체의 생성
    아래는 add() 메서드 수행 후 multi() 메서드가 수행되는 시점 실행과 메모리3

3. 참고하면 좋은 내용

3.1. 참고

public class MemoryArchitecture { 
    // Member Variable(Intance Variable)
    // 객체를 생성할때 Heap에 올라간다.
    int n1 = 10;
	
    // Member Variable(Intance Variable)
    // 객체를 생성할때 Heap에 올라간다. "Hello"는 string constant pool에 저장되고 s1은 이를 가리킨다.
    String s1= "Hello";
	
    // Class Variable
    // Class가 로드될때 Method 영역(static 영역)에 올라간다.
    static int n2= 10;
	
    // final static 으로 선언하면 Class가 로드될때 Constant Pool 복사
    static final int n3= 20; 
	
    // parameter Variable
    public static void t1(int a) { 
        // a, a1, b2 모두 stack에 올라간다.
        int a1;
        int b2;
    }
}

3.2. String과 메모리

String과 메모리 포스팅을 참고할 것.


[참고 문서]

카테고리:

업데이트:

댓글남기기