메모리 구조(JAVA)

권 해·2023년 2월 12일
1

Java

목록 보기
4/5

C로 처음 프로그래밍 언어를 배우기 시작하면서 지금까지, 힙 영역과 스택 영역과 같은 메모리 구조에 대해 여러번 접한적이 있다.
하지만 "지금은 몰라도 되겠지", "몰라도 코딩하는데 문제 없으니까 일단 넘어가자" 라는 마인드로 미루었었다.
최근 들어 메모리 관리의 중요성을 느끼면서, 이제는 모르면 안되는 부분이라는 생각이 들었기 때문에 포스팅하면서 공부해보려 한다.

JVM
자바 가상 머신 JVM(Java Virtual Machine)은 자바 프로그램 실행환경을 만들어 주는 소프트웨어이다. 자바 코드를 컴파일하여 .class 바이트 코드(바이너리 파일)로 만들면 이 코드가 자바 가상 머신 환경에서 실행된다. JVM은 자바 실행 환경 JRE(Java Runtime Environment)에 포함되어 있다. 현재 사용하는 컴퓨터의 운영체제에 맞는 자바 실행환경 (JRE)가 설치되어 있다면 자바 가상 머신이 설치되어 있다는 뜻이다.

JVM은 다음과 같은 역할을 한다.

  • 바이너리 코드를 읽는다.
  • 바이너리 코드를 검증한다.
  • 바이너리 코드를 실행한다.
  • 실행환경(Runtime Environment)의 규격을 제공한다. (필요한 라이브러리 및 기타파일

자바 프로그램이 실행되면 JVM(자바 가상 머신)은 OS로부터 메모리를 할당받고, 그 메모리를 용도에 따라서 여러 영역으로 나누어 관리를 한다.
JVM의 메모리 공간은 크게 Method(Static) 영역, Stack 영역, Heap 영역으로 구분되고 데이터 타입(자료형)에 따라 각 영역에 나눠서 할당 되게 된다.

자바 가상 머신(JVM)의 동작 방식
1. 자바로 개발된 프로그램을 실행하면 JVM은 OS로부터 메모리를 할당받는다.
2. 자바 컴파일러(javac)가 자바 소스코드(.java)를 자바 바이트코드(.class)로 컴파일한다.
3. Class Loader를 통해 JVM Runtime Data Area로 로딩한다.
4. Runtime Data Area에 로딩 된 .class들은 Execution Engine을 통해 해석된다.
5. 해석된 바이트 코드는 Runtime Data Area의 각 영역에 배치되어 수행하며 이 과정에서 Execution Engine에 의해 가비지 컬렉터의 작동과 스레드 동기화가 이루어진다.

클래스 로더(Class Loader)
자바는 동적으로 클래스를 읽어오므로, 프로그램이 실행 중인 런타임에서야 모든 코드가 자바 가상 머신과 연결된다. 이렇게 동적으로 클래스를 로딩해주는 역할을 하는 것이 바로 클래스 로더(class loader)이다.
자바에서 소스를 작성하면 .java파일이 생성되고 .java소스를 컴파일러가 컴파일하면 .class파일이 생성되는데 클래스 로더는 .class 파일을 묶어서 JVM이 운영체제로부터 할당받은 메모리 영역인 Runtime Data Area로 적재한다.

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

가비지 컬렉터(Garbage Collector)
자바 가상 머신은 가비지 컬렉터(garbage collector)를 이용하여 더는 사용하지 않는 메모리를 자동으로 회수해준다. 따라서 개발자가 따로 메모리를 관리하지 않아도 되므로, 더욱 손쉽게 프로그래밍을 할 수 있도록 도와준다. Heap 메모리 영역에 생성(적재)된 객체들 중에 참조되지 않은 객체들을 탐색 후 제거하는 역할을 한다. GC역할을 수행하는 스레드를 제외한 나머지 모든 스레드들은 일시정지 상태가 된다.

런타임 데이터 영역 (Runtime Data Area)
런타임 데이터 영역은 JVM의 메모리 영역으로 자바 애플리케이션을 실행할 때 사용되는 데이터들을 적재하는 영역이다.
자바의 메모리 공간은 Method(Static) Area, Stack Area, Heap Area로 구분된다.
데이터 타입에 따라서 그에 맞는 공간에 할당되고 구동하는 방식 또한 서로 상이하다.

1) 메서드(정적) 영역 (Method Area)

  • JVM이 동작해서 클래스가 로딩될 때 생성.
  • JVM이 읽어들인 클래스와 인터페이스 대한 런타임 상수 풀, 멤버 변수(필드), 클래스 변수(Static 변수), 상수(final), 생성자(constructor)와 메소드(method) 등을 저장하는 공간.
  • Method(Static) 영역에 있는 것은 어느곳에서나 접근 가능
  • Method(Static) 영역의 데이터는 프로그램의 시작부터 종료가 될 때까지 메모리에 남아있다. 그래서 static 메모리에 있는 데이터들은 프로그램이 종료될 때까지 어디서든 사용이 가능하다. 그러나 static 데이터를 무분별하게 많이 사용할 경우 메모리 부족 현상이 일어날수 있게 된다.

2) 스택 영역 (Stack Area)

  • 메소드 내에서 정의하는 기본 자료형에 해당되는 지역변수의 데이터 값이 저장되는 공간
  • 메소드가 호출될때 스택 영역에 스택 프레임이 생기고 그안에 메소드를 호출
  • primitive 타입의 데이터(int, double, byte, long, boolean 등) 에 해당되는 지역변수, 매개 변수 데이터 값이 저장
  • 메소드가 호출 될 때 메모리에 할당되고 종료되면 메모리에서 사라짐
  • Stack 은 후입선출 LIFO(Last-In-First-Out) 의 특성을 가지며, 스코프(Scope) 의 범위를 벗어나면 스택 메모리에서 사라진다.

3) 힙 영역 (Heap Area)

  • JVM이 관리하는 프로그램 상에서 데이터를 저장하기 위해 런타임 시 동적으로 할당하여 사용하는 영역
  • 참조형(Reference Type) 데이터 타입을 갖는 객체(인스턴스), 배열 등이 저장 되는 공간
  • 단, Heap 영역에 있는 오브젝트들을 가리키는 레퍼런스 변수는 Stack에 적재
  • Heap 영역은 Stack 영역과 다르게 보관되는 메모리가 호출이 끝나더라도 삭제되지 않고 유지된다. 그러다 어떤 참조 변수도 Heap 영역에 있는 인스턴스를 참조하지 않게 된다면, GC(가비지 컬렉터)에 의해 메모리에서 청소된다.
  • Stack은 스레드 갯수마다 각각 생성되지만, Heap은 몇개의 스레드가 존재하든 상관없이 단 하나의 heap 영역만 존재

정리

  • 힙 메모리는 애플리케이션의 모든 부분에서 사용되며, 반면에 스택 메모리는 하나의 스레드가 실행될 때 사용. 그래서 힙 과 메서드 공간에 저장된 객체는 어디서든지 접근이 가능하지만, 스택 메모리는 다른 스레드가 접근할 수 없다.
  • 언제든지 객체가 생성되면 항상 힙 공간에 저장되며, 스택 메모리는 힙 공간에 있는 객체를 참조만 한다. 즉, 스택 메모리는 primitive 타입의 지역변수와 힙 공간에 있는 객체 참조 변수만 갖고 있다.
  • 스택메모리의 생명주기는 매우 짧으며, 힙 메모리는 애플리케이션의 시작부터 끝까지 살아남는다.
  • 스택 메모리가 가득차면 자바에서는 java.lang.StackOverFlowError를 발생, 힙 메모리가 가득차면 java.lang.OutOfMemoryError : Java Heap Space 에러를 발생
  • 스택 메모리 사이즈는 힙 메모리와 비교했을 때 매우 적다. 하지만 스택 메모리는 간단한 메모리 할당 방법(LIFO)를 사용하므로 힙 메모리보다 빠르다.

이렇게 자바 프로그램이 실행되어 OS로부터 메모리를 할당받아 메모리 영역을 사용하고, 프로그램이 종료되어 메모리가 해제되는 과정까지 쭉 알아보았다.
이제서야 static으로 선언된 변수, 지역변수, 동적 할당된 인스턴스 의 메모리가 언제 어디서 할당되고, 어디서 해제되는지 전부 이해가 간다.
지금까지 컴퓨터 공학을 배우고 코딩을 한다고 하면서 이것도 제대로 이해하지 못하고 있었다는 것이 부끄럽게 느껴졌다.
정말 매우 중요한 내용이니 확실하게 이해하고 넘어가도록 해야겠다.

참고 자료

1개의 댓글

comment-user-thumbnail
2023년 2월 12일

진짜 깔끔하게 이해가 되네요 좋은 글 감사합니다 :)

답글 달기