자바의 메모리 구조

박진선·2022년 11월 4일
0

JVM의 전체적인 구조


JVM(Java Virtual Machine)
자바 프로그램 실행환경을 만들어 주는 소프트웨어 이다. 자바 코드를 컴파일하여 .class 바이트 코드로 만들면 이 코드가 자바 가상 머신 환경에서 실행된다.
.class 파일은 바이트 코드 라고 하는데 사람이 쓰는 자바 코드에서 컴퓨터가 읽는 기계어로의 중간 단계 이며 java 언어로 작성된 java 파일은 컴파일 하면 .class 파일이 생성되고 생성된 바이트 코드는 각자의 플랫폼에 설치되어 있는 JVM이 운영체제에 맞는 실행 파일로 바꿔준다
java는 컴파일된 바이트코드로 어떤 jvm에서도 동작이 가능하기에 플랫폼에 의존적이지 않지만 jvm은 플랫폼에 의존적이다 윈도우와 리눅스 jvm은 서로 다름
생성한 .java 파일을 컴파일하면 javac 에 의해 .class 파일이 만들어짐, 이후 클래스 로더를 통해 JVM Runtime Data Area로 로딩되고 로딩된 .class 바이트 코드를 실행할 컴퓨터에 깔린 JVM에 가져다주면 그 컴퓨터가 이 프로그램을 실행할 때 JVM 이 기계어로 해석한다

소스코드(Source Code)

  • 컴퓨터 프로그램을 사람이 읽을 수 있는 프로그래밍 언어로 기술한 텍스트 파일이다.
    즉 코딩한 자바 코드를 말함

컴파일러(Java Compiler)

  • 자바 소드코드를 컴파일하여 자바 가상 머신이 이해할 수 있는 자바 바이트 코드(.class 파일)로 변환하는 역할을 한다.

  • JDK를 설치하면 javac.exe라는 실행 파일 형태로 설치된다

클래스 로더(Class Loader)

  • 클래스 로더는 런타임 중에 JVM의 메소드 영역에 동적으로 Java 클래스를 로드하는 역할을 한다. JVM은 실행될때 모든 클래스를 메모리에 올려놓지 않는다. 그때 마다 필요한 클래스를 메모리에 올려 효율적으로 관리하기 위함이다. 하나의 클래스를 로딩하는 과정에서 동적으로 다른 클래스를 로딩하는 로드타임 동적 로딩 방식과 코드를 실행하는 순간에 클래스를 로딩하는 런타임 동적 로딩 방식이 있다. 하나의 클래스는 단 한번만 로드되므로 코드의 다른 곳에서 이미 로드된 클래스의 멤버를 호출하더라도 이미 로드된 클래스라면 더 이상 클래스가 로드되는 과정은 없다

클래스 로더에는 로딩, 링크 초기화 단계로 나뉘어져 있다.

  • 로딩
    자바 바이트 코드(.class)를 메소드 영역에 저장한다.
    각 자바 바이트 코드(.class)는 JVM에 의해 메소드 영역에 다음 정보들을 저장한다.
    로드된 클래스를 비롯한 그의 부모 클래스의 정보
    클래스 파일과 Class, Interface, Enum의 관련 여부
    변수나 메소드 등의 정보

  • 링크
    검증: 읽어 들인 클래스가 자바 언어 명세 및 JVM 명세에 명시된 대로 잘 구성되어 있는지 검사한다.
    준비: 클래스가 필요로 하는 메모리를 할당하고, 클래스에서 정의된 필드, 메소드, 인터페이스를 나타내는 데이터 구조를 준비한다.
    분석: 심볼릭 메모리 레퍼런스를 메소드 영역에 있는 실제 레퍼런스로 교체한다.

  • 초기화
    클래스 변수들을 적절한 값으로 초기화 한다. 즉, static 필드들이 설정된 값으로 초기화한다.

  • 클래스 로딩 시점
    클래스의 인스턴스가 생성될때, 클래스의 정적 변수가 사용될때 (단, 정적 변수는 final로 선언된 상수는 로딩 안됨), 클래스의 정적 메소드가 호출될때, static 내부클래스의 static 변수, 메소드를 호출할 경우 에는 내부 클래스만 로딩됨, 외부 클래스가 로딩 될 때 내부 클래스는 로딩 안됨

  • 초기화 시점
    클래스의 인스턴스 생성, 클래스의 정적 변수 사용 (final 키워드 X), 클래스의 정적 메소드 호출

실행 엔진(Execution Engine)
클래스 로더에 의해 JVM으로 로드된 .class 파일(바이트코드)들은 Runtime Data Areas의 Method Area에 배치되는데 배치 이후에 JVM은 Method Area의 바이트 코드를 실행 엔진(Execution Engine)에 제공하여 정의된 내용대로 바이트 코드를 실행시킨다.
이때, 로드된 바이트코드를 실행하는 런타임 모듈이 실행 엔진임 바이트코드를 명령어 단위로 읽어서 실행한다.

가비지 컬렉터(Garbage Collector)
Heap 메모리 영역에 생성(적재)된 객체들 중에 참조되지 않은 객체들을 탐색 후 제거하는 역할을 한다.


런타임 데이터 영역 (Runtime Data Area)

  • JVM의 메모리 영역으로 자바 애플리케이션을 실행할 때 사용되는 데이터들을 적재하는 영역
  • 모든 스레드가 공유해서 사용하는 영역 (GC의 대상) : 힙 영역 (Heap Area), 메서드 영역(Method Area)
  • 스레드(Thread) 마다 하나씩 생성 하는 영역 : 스택 영역(Stack Area), PC 레지스터 (PC Register), 네이티브 메서드 스택(Native Method Stack)

메소드 영역 (Method Area) 또는 클래스 영역(Class area)

  • 클래스 멤버 변수의 이름, 데이터 타입, 접근 제어자 정보와 같은 각종 필드 정보들과 메서드 정보, 데이터 Type 정보, Constant Pool, static변수, final class 등이 생성되는 영역이다.
    메서드 구현 코드는 클래스 영역에 저장되고 Heap영역에 저장된 객체 안에서는 그 위치를 가리키고 있다, 즉 같은 클래스로 만든 모든 객체는 동일한 메소드 값을 공유한다.
    Heap 영역에 생성된 객체에서 필드값은 실제 저장공간이 객체 내부에 있고 메소드는 메소드 영역에 하나만 저장하여 같은 클래스의 객체 끼리 공유한다.

힙 영역 (Heap Area)

  • new 키워드로 생성된 객체와 객체안의 모든 인스턴스 변수 메소드, Array와 같은 동적으로 생성된 데이터가 저장되는 영역, Reference Type 의 데이터가 저장되는 공간, 주기적으로 GC가 관리한다.

스택 영역 (Stack Area)

  • 지역변수, 파라미터, 리턴 값, 연산에 사용되는 임시 값 등이 생성되는 영역, Last In First Out, 나중에 들어온 데이터가 먼저 나간다.
    지역변수 이지만 Reference Type일 경우에는 Heap 에 저장된 데이터의 주소값을 Stack 에 저장해서 사용한다.

PC 레지스터 (PC Register)

  • Thread가 생성될 때마다 생성되는 영역으로 프로그램 카운터, 즉 현재 스레드가 실행되는 부분의 주소와 명령을 저장하고 있는 영역이다.

네이티브 메서드 스택 (Native Method Stack)

  • 자바 이외의 언어(C, C++, 어셈블리 등)로 작성된 네이티브 코드를 실행할 때 사용되는 메모리 영역으로 일반적인 C 스택을 사용한다.
    보통 C/C++ 등의 코드를 수행하기 위한 스택을 말하며 (JNI) 자바 컴파일러에 의해 변환된 자바 바이트 코드를 읽고 해석하는 역할을 하는 것이 자바 인터프리터(interpreter) 이다.

나의 2번째 블로깅이다😁 이번 기회에 JVM 메모리 구조에 대해서 구글링도 많이 해보고 정리하여 작성하다보니 어느정도 감이 잡히는 시간이 됬다 잊어먹을 때 마다 와서 다시 읽어야지🤣

2022.11.04 21:40 작성

profile
주니어 개발자 입니다

0개의 댓글