Today
-
Yesterday
-
Total
-
  • 자바 메모리 모델 Java Memory Model
    Language/Java 2023. 11. 30. 00:01

    자바 메모리 모델은 자바 프로그램의 동시성을 다루는 메모리 동작에 대한 명세 = JVM이 동시에 실행되는 스레드 간의 메모리 접근을 어떻게 조정하는지에 대한 설명 이다.

    🙈;;

    아직은 너무 어려운 내용이었다. 일단 기록!


    1. 메모리 배치 Memory Layout

    요약

    저장 영역 종류
    Stack 로컬 변수
    Stack 메소드 반환 값
    Stack 메소드 호출 완료 후 실행이 이어질 위치 주소
    - -
    Heap 객체
    Heap 인스턴스 변수 = 멤버 변수
    Heap static 변수
    - -
    Method 영역 Metaspace 상수 풀 (클래스 및 인터페이스의 상수, 리터럴, 심볼릭 참조 등)
    Method 영역 Metaspace 클래스 메타데이터 (클래스 이름, 접근 제어자, 인터페이스, 슈퍼클래스 등 클래스와 관련된 정보)
    Method 영역 Metaspace 메소드 메타데이터 (메소드의 바이트코드, 리턴 타입, 파라미터, 예외 등 메소드와 관련된 정보)

    자바 메모리 모델의 메모리 배치를 이해하면 프로그램이 메모리를 어떻게 사용하는지, 객체와 변수가 어떻게 저장되는지, 메모리 관리와 가비지 컬렉션의 동작 원리를 파악할 수 있다.

    이를 통해 효율적인 코드를 작성하고 성능 문제를 해결하는데 도움이 된다!

    1-1. Stack 메모리

    각 스레드에 할당되며, 메소드 호출과 관련된 정보를 저장하는 데 사용된다. 메소드 호출이 발생할 때마다 스택 프레임이라는 블록이 생성된다.

    스택 프레임은 다음과 같은 정보를 포함한다.

    * 로컬 변수

    메소드 내에서 선언된 변수들의 값이 저장됨. 기본 데이터 타입의 변수들은 직접 저장되며, 객체 참조 변수들은 해당 객체에 대한 참조를 저장한다.

    * 반환 값

    메소드가 반환하는 값이 저장됨.

    * 반환 주소

    메소드 호출이 완료된 후에 실행을 이어가야 할 위치를 저장.


    스택 메모리는 후입선출 ( Last In First Out ) 방식으로 동작한다.

    즉, 가장 최근에 생성된 스택 프레임이 가장 먼저 제거된다.

    스택 메모리는 상대적으로 빠른 접근 속도를 가지며, 메소드 호출이 끝나면 자동으로 메모리가 해제된다.


    1-2. Heap 메모리 ( 자바 버전 ≥ java8 )

    모든 스레드가 공유하며, 객체와 인스턴스 변수(= 멤버 변수), 정적 변수(= static)을 저장하는 데 사용된다.

    객체 생성 시 JVM은 힙 영역에 객체를 할당하고, 해당 객체의 참조를 반환한다.

    힙 메모리는 다음과 같은 특징을 가진다.

    * 가비지 컬렉션 Garbage Collection

    힙 영역에서 더 이상 참조되지 않는 객체가비지 컬렉터에 의해 자동으로 메모리에서 해제된다.

    가비지 컬렉션은 메모리 관리를 단순화 하며, 메모리 누수를 방지하는 데 도움이 된다.

    * 크기 조절 가능

    힙 메모리의 크기는 프로그램의 요구에 따라 변경될 수 있다. 힙 메모리가 부족하면 JVM은 더 많은 메모리를 할당할 수 있으며, 가용 메모리가 충분하면 힙 메모리 크기를 줄일 수도 있다.

    이러한 크기 조절은 JVM의 옵션을 통해 설정할 수 있다.

    * 매모리 세분화 Fragmentation

    힙 메모리에 객체가 생성되고 해제되는 과정에서 메모리 공간이 파편화 될 수 있는데,

    가비지 컬렉션 과정에서 메모리 정리를 수행해 파편화를 줄일 수 있다.

    힙 메모리는 다음과 같은 영역으로 세분화 된다.

    • Young 영역 Young Generation 객체가 생성되는 영역. 이 영역은 메모리 관리의 관점에서 에덴(Eden) 영역과 두 개의 서바이버(Survivor) 영역(S0, S1)으로 세분화 되어 나뉜다. * 에덴 영역 : 객체가 처음 생성되는 영역 * 서바이버 영역 : 가비지 컬렉션 과정에서 살아남은 객체를 저장하는 영역

    • 테넌트 영역 Tenured Generation 또는 오래된 영역 Old Generation 객체가 일정 시간 동안 살아남으면 이동하는 영역. 이 객체는 가비지 컬렉션의 주요 대상이 아닌 것으로 간주되며, 프로그램의 수명 동안 메모리에 남아있는다. 이 영역의 가비지 컬렉션은 전체 힙 메모리를 대상으로 진행되는 Full Garbage Collection에 의해 수행된다.

    가비지 컬렉터는 적절한 시점에 힙 영역을 스캔하여 참조되지 않는 객체를 찾고, 메모리를 해제하여 사용 가능한 공간을 확보한다.

    주로 사용되는 가비지 컬렉션 알고리즘에는 마크 앤 스위프 Mark and Sweep, 복사 Copying, 세대 Generational 등이 있다.


    1-3. Metaspace (자바 버전 ≥ java8 )

    Metaspace에서는 아래와 같은 정보들을 관리한다.

    • 클래스 관련 메타데이터 클래스 이름, 접근 제어자, 인터페이스, 슈퍼클래스 등 클래스와 관련된 정보

    • 메소드 관련 메타데이터 메소드의 바이트코드, 리턴 타입, 파라미터, 예외 등 메소드와 관련된 정보

    • 상수 풀 클래스 및 인터페이스의 상수, 리터럴, 심볼릭 참조 등. 상수 풀은 클래스의 로딩 과정에서 생성되며, 클래스에 대한 메타데이터와 함께 Metaspace에 저장된다.


    java8 이전까지 Metaspace 영역은 Heap 메모리상의 Permanent 영역으로 동작해왔다.

    Heap 영역의 크기는 JVM 이 관리하고 있기 때문에, Permanent 영역의 크기 역시 JVM이 관리하고 있었는데, 이로 인해 OutOfMemory 이슈를 자주 접할 수 있었다.

    하지만 java8로 버전 업데이트 되면서, Heap 영역 밖의 Metaspace 영역이라는 , 네이티브 영역으로 존재하게 되었고 네이티브 영역의 메모리 관리는 OS가 하기 때문에, OutOfMemory 이슈도 볼 수 없게 되었고 개발자가 영역 확보에 대한 고민을 크게 하지 않아도 되는 환경이 되었다.

    또한 Heap 영역에서 네이티브 영역으로 위치가 변경되면서 가비지 컬렉터의 관리 대상에서 제거되었다.

    보고 공부한 블로그: johngrib.github

    오, 이것도 이제는 옛날 옛적 이야기가 되었다. 지금 나온 최신 버전이 20 ...! 🙊 그래도 알고나면 재밌으니 남겨둡니다..😔



    2. 스레드 간 상호 작용

    자바 메모리 모델은 각 스레드의 로컬 메모리와 공유 메모리 사이에서 값이 어떻게 전달되는지 정의한다.

    이를 통해 데이터의 가시성(visibility)과 순서(ordering)를 보장한다.

    데이터의 가시성 Visibility

    가시성은 한 스레드가 다른 스레드에 의해 변경된 변수의 값을 읽을 수 있는 시점을 말한다.

    가시성 문제는 데이터 변경 사항이 올바른 순서로 공유되지 않아 발생한다.

    자바에서는 동기화volatile 키워드를 사용하여 가시성 문제를 해결할 수 있다.

    데이터의 순서 Ordering

    메모리 동작의 순서는 스레드 간의 실행 순서를 나타낸다.

    동시성 프로그래밍에서는 메모리 동작의 순서를 명확하게 정의해야 한다.

    자바 메모리 모델은 Happens-Before 관계를 통해 메모리 동작의 순서를 명시한다.



    3. 동기화

    자바는 동기화된 메소드와 블록, 그리고 volatile 키워드를 사용하여 스레드 간의 안전한 데이터 공유를 지원한다. 이러한 도구들은 데이터의 가시성, 순서, 원자성을 보장하며 스레드 간의 경쟁 상태를 방지하는데 도움이 된다.



    4. 미리 발생 Happens-Before

    메모리 동작 간의 순서를 정의하는 개념이다. Happens-Before 순서는 데이터의 가시성과 순서를 보장하기 위해 동기화를 사용하는 프로그램에서 매우 중요하다.



    5. 원자성 Atomicity

    자바 메모리 모델은 원자성을 통해 동시성 문제를 처리한다. 원자적 연산은 여러 스레드에 의해 중단되거나 중복 실행되지 않는 연산이다. 자바는 원자적 연산을 위해 java.util.concurrent.atomic 패키지의 클래스를 제공한다.

    'Language > Java' 카테고리의 다른 글

    enum 클래스  (0) 2023.11.30
    Optional  (0) 2023.11.30
    싱글톤 패턴  (0) 2023.11.30
    OkHttp3 라이브러리 사용 with 비동기  (0) 2023.11.29
    Thread  (0) 2023.11.29

Designed by Tistory / Custom by 얼거스