ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • JVM2
    프로그래밍 언어/JAVA 2020. 4. 26. 16:20

    Runtime Data Areas

    • Runtime Data Areas의 구조
    • PC Registers
    • Java Virtual Machine Stacks
    • Native Method Stacks
    • Method Area
    • Java Heap
    • Runtime Data Area Simulation

     

    Runtime Data Areas의 구조

    Process로서 JVM이 프로그램을 수행하기 위해 OS로부터 할당 받은 메모리 영역

    Runtime Data Areas는 각각의 목적에 따라 5개의 영역으로 나뉨

      • PC Registers                                 Thread 별 생성
      • Java Virtual Machine Stacks         Thread 별 생성
      • Native Method Stacks                   Thread 별 생성
      • Method Area                                 Thread에게 공유
      • Heap                                             Thread에게 공유

    내용

     

    PC Registers

    Java는 Stack-Base로 작동

    JVM은 CPU에 직접 Instruction을 수행하지 않고 Stack에서 Operand를 뽑아내어 이를 별도의 메모리 공간(PC Registers)에 저장하는 방식

    Java는 플랫봄별 도립적으로 동작, 하지만 JVM도 OS나 CPU 입장에서 머신에서 동작하는 하나의 프로세스

    Java도 현재 작업하는 내용을 CPU에 Instruction을 제공해야함 → 이를 위한 버퍼 공간으로 PC Registers라는 메모리 영역 생성

     

    PC Registers는 Thread 마다 하나씩 존재, Thread가 시작할 때 생성

    만약 Thread가 Java Method를 수행하고 있으면 PC Register에는 현재 수행 중인 JVM Instruction의 주소를 가지게 됨

    반면, C언어 등과 같은 Native Method를 수행하고 있다면 PC Registers는 undefined로 있게됨

     

    Java Virtual Machine Stacks

    Thread의 수행정보를 기록하는 Frame을 저장하는 메모리 영역

    Java Virtual Machine Stacks은 Thread 별로 존재하며 Thread가 시작할 때마다 생성

    다른 Thread는 접근할 수 없기 때문에 동기화 이슈는 발생하지 않음

    ex) Local Variables

     

    JVM은 Stack Frame을 Java Virtual Machine Stack에 단순 push 및 pop 작업만을 수행

    Stack Frame 중에 현재 수행하는 Method의 정보를 저장하는 것을 Current Frame이라고 하고 현재 수행하고 있는 Method의 클래스를 Current Class라고 함

    Stack Frame에는 Method의 Parameter Variables, Local Variables, 연산의 결과 등과 같은 데이터들을 저장

     

    Thread가 Java Method를 하나 수행하게 되면 JVM은 Stack Frame을 하나 생성하여 Java Virtual Machine Stacks에 push 함

    그래서 새롭게 들어간 Stack Frame은 Current Frame이 됨

    해당 Method가 수행을 마치게 되면 Java Virtual Machine Stacks에서 pop하게 되고 이전의 Stack Frame이 Current Frame이 됨

    그리고 만약 비정상 처리가 되어 Exception 처리를 하는 작업을 수행한 후 Java Virtual Machine Stacks에서 사라지게 됨

     

    Stack Frame

    Thread가 수행하고 있는 Application를 Method 단위로 기록하는 곳

    Stack Frame

        • Local Variable Section
        • Operand Stack
        • Frame Data

    Stack Frame은 Class의 메타 정보를 이용하여 적절한 크기로 고정됨 ← compile time에 크기를 결정가능함

     

    Local Variable Section

    Method의 Parameter Variable과 Local Variable 들을 저장

    Local Variable Section은 0부터 시작하는 인덱스를 가진 Array로 구성, Array의 인덱스를 통해 데이터에 접근

    Method의 Parameter Variable는 선언된 순서로 인덱스가 할당, Local Variable는 compiler가 알아서 인덱스를 할당

     

    Parameter Variable과 Local Variable이 int와 같은 Primitive Type인 경우 고정된 크기로 할당

    Object나 Array, String과 같은 객체는 가변크기로 reference 현으로 할당 받음

    객체정보는 Local Variable Section이나 Stack Frame이나 Java Virtual Machine Stacks에 직접적으로 저장되는 것이 아니라 해당 객체가 존재하는 Heap의 위치를 말해주는 Reference를 저장

     

    char, byte, short, boolean 형으로 선언한 것들이 Local Variable Section에서는 모두 int 형으로 할당

    Primitive Type이라 할지라도 JVM의 지원여부와 JVM Stacks의 저장형태에 따라 달라짐

    char, byte, short, boolean 는 Local Variable Section이나 Operand Stack에서는 Int 형으로 변환되어 저장/ Heap에서는 원래의 형으로 저장

     

    0번 인덱스의 경우 hidden this로 정의

    모든 Local Method 혹은 Instance Method에 무조건 포함, 여기에 저장된 Reference를 통해 Heap에 있는 Class의 instance 데이터를 찾게 됨

    Operand Stack

    내용

    JVM의 작업 공간 - JVM이 프로그램을 수행하면서 연산을 위해 사용되는 데이터 및 그 결과를 Operand Stack에 집어넣고 처리

    Operand Stack,  Array로 구성

    Frame Data

    Constant Pool Resolution 정보와 Method가 정상 종료했을 때의 정보들 그리고 비정상 종료했을 시에 발생하는 Exception 관련 정보들을 저장

    Constant Pool Resolution

    Resolution은 Symbolic Reference로 표현된 Entry를 찾아 Direct Reference로 변경하는 과정을 의미

    Class의 모든 Symbolic Reference는 Method Area의 Constant Pool이라는 곳에 저장, Resolution을 Constant Pool Resolution이라고 명함

    Frame Data에 저장된 Constant Pool Resolution은 관련 Constant Pool의 Pointer 정보, JVM은 이 Pointer를 이용하여 필요할 때 마다 Constant Pool을 찾아감

    보통 상수를 가져올 때 Constant Pool의 Entry 정보를 참조하기도 하지만 다른 Class를 참조하거나 Method를 수행하거나 아니면 특정 변수를 접근할 때에도 Constant Pool를 참조

    Java의 모든 Reference는 Symbolic Reference 이므로 Class나 Method 그리고 변수나 상수에 접근할 때에도 이러한 Resolution이 수행

    그리고 특정 Object가 특정 Class나 Interface에 의존 관계가 있는지 확인하기 위해서도 Constant Pool의 Entry 참조

     

    JVM Stacks에 Current Frame이 pop이 되고 사라지면 이전에 이 Method를 호출했던 Method의 Stack Frame이 Current Frame이 됨, 여러 Stack Frame 중 어디로 돌아가는가?

    Frame Data에는 자신을 호출한 Stack Frame의 Instruction Pointer가 존재함

    Method가 종료되면 JVM은 이 정보를 PC Register에 설정하고 Stack Frame을 빠져나감

    해당 Method의 반환값이 있다면 이 반환값을 Current Frame 즉, 자신을 호출한 Method의 Stack Frame의 Operand Stack에 Push하는 작업 병행

    Native Method Stacks

    Java는 Java 외의 언어로 작성된 프로그램, API 툴킷 등과이 통합을 쉽게 하기 위하여 JNI(Java Native Interface)라는 표준 규약을 제공

    즉, Native Code 로 되어 있는 Fuction의 호출을 Java 프로그램 내에서 직접 수행할 수도 있고 그 결과 값을 받아 올 수 있게 됨

     

    JNI의 경우 앞서 말한 Stack과 Stack Frame과 유사한 방식을 통해 Method 호출 → Native Method Stacks

    Native Method Stacks은 Native Code가 C로 작성되 있으면 C stack으로 C++로 생성되어있으면 C++ stack으로 생성

    Native Method Stacks이 끝나면 다시 Thread의 Java Virtual Machine Stacks로 돌아옴

    이때, Native Method를 호출한 Stack Frame으로 돌아오는 것이 아닌 새로운 Stack Frame을 생성하여 다시 작업을 수행

     

    Hotspot JVM이나 IBM JVM은 앞서 Java Virtual Machine Stacks과 Native Method Stacks을 구분하지 않음 → Native Stack으로 통합

    그렇기 때문에 Java Method를 수행하는지 아니면 Native Method를 수행하는지를 따져 Stack Frame이 Java Stack Frame인지 Native Stack Frame인지 구분할 뿐

    Method Area

    내용

    모든 Thread 들이 공유하는 메모리 영역

    이 영역은 Load 된 Type(Class 나 Interface)을 저장하는 논리적 메모리 공간

    Method Area는 JVM이 기동할 때 생성이 되며 Garbage Collection의 대상

    Method Area 벤더마다 다르게 구현

     

    Type Information in Method Area

    • Type Information
    • Constant Pool
    • Field Information
    • Method Information
    • Class Variables
    • Reference to class - ClassLoader
    • Reference to class - Class

     

    Type Information

    가장 기본이 되는 정보, Type에 대한 전반적인 내용 포함

    Full Qualified Name - Package.class 형태를 지니는 Type의 전체 이름

    Type의 직계 super class의 전체 이름 (Type이 interface이거나 java.lang.object class이거나 super class가 없는 경우 제외)

    Type이 Class인지 Interface인지 여부

    Type의 Modifier

    Interface인 경우 직접 Link 되고 있는 객체의 리스트로 객체는 전체 이름(package.class)으로 표현됨

     

    Constant Pool

    전체 JVM에서 가장 중요한 역할을 수행하는 곳

    Type의 모든 Constant 정보를 가지고 있는 부분

    여기서 Constant는 상수는 물론 Literal Constant, Type, Field(Member Variable, Class Variable), Method로의 모든 Symbolic Reference까지 확장한 개념

    앞서 Symbolic Reference 언급하였는데 Constant Pool 내에 저장됨, JVM은 실행 시 참조하는 객체에 접근할 필요가 있으면 Constant Pool의 Symbolic Reference를 통해 해당 객체가 위치한 메모리 주소를 찾아 동적으로 연결

     

    Field Information

    Type에서 선언된 모든 Field의 정보

    Field Information에는 Field의 정보가 선언된 순서대로 기록

    • Field 이름
    • Field의 Data Type, 선언된 순서
    • public, private, protected, static, final, volatile, transient 와 같은 Field의 Modifier

     

    추가

    Variable

      • Instance Variable ----- Field (non-static)
      • Class Variable --------- Field (static)
      • Local Variable --------- method에 속함
      • Parameter -------------- method에 속함

     

    Method Information

    Type에 선언된 모든 Method의 정보를 의미

    • Method 이름
    • Method의 반환 값의 Data Type 또는 void
    • Method Parameter의 수와 Data Type, 선언된 순서
    • public, private, protected, static, final, synchronized, native, abstract 와 같은 Method의 Modifier

    만약, Method가 native나 abstract가 아니라면 다음의 정보가 추가됨

      • Method의 Bytecode
      • Method의 Stack Frame의 Operand Stack 및 Local Variable Section의 크기
      • Exception Table 

     

    Class Variables

    Class에서 static으로 선언된 변수

    Class에서 하나의 값으로 유지

    해당 변수는 Instance에 공유되기 때문에 이를 이용하는데 있어 동기화 이슈 발생

    Class Variable을 final로 선언할 경우 이를 변수가 아닌 상수 취급하며 Constant Pool에 Literal Constant로 저장

     

    Reference to class - ClassLoader

    Type이 JVM에 Load 될때 항상 이 Type은 어떤 ClassLoader를 경유하여 Loading 되었는지를 추적하게 됨

    한 Type이 다른 Type을 참조할 때 같은 ClassLoader를 사용하도록 되어 있음

    User-Defined ClassLoader - 해당 ClassLoader의 Reference를 Type의 정보 중 하나로 저장하게 됨

    Bootstrap ClassLoader - Reference가 Null로 저장

    위 정보는 Dynamic Linking을 할 때 해당 Type과 동일한 ClassLoader를 통해 참조하는 Type을 Loading 하기 위해 사용

     

    Reference to class - Class

    Type이 JVM에 Load 되면 항상 java.lang.class Class의 Instance가 하나 생성됨

    Method Area에는 Type 정보의 일부로 이 Instance의 Reference를 저장하고 있음

     

    Method Table

    Java는 캡슐화된 객체를 이용하는 프로그래밍 언어로 Reference를 통해 객체를 찾아 다니는 일이 프로그램 수행 중 빈번히 일어남

    Method Area에서 원하는 정보를 찾는 속도는 성능의 중요한 이슈!

    이를 위해 JVM을 설계하는 사람들은 Method Table이라는 데이터구조 사용

     

    Heap

    내용

    Instance(또는 Object)와 Array 객체 두 가지 종류만 저장되는 공간

    모든 Thread 들에 의해 공유되는 공간

    같은 Application을 사용하는 Thread 사이에서는 공유된 Heap Data를 이용할 때 동기화 이슈가 발생할 수 있음

    JVM은 Java Heap에 Memory를 할당하는 Instruction(Bytecode로 new, newarray, anewarray, multianewarray)만 존재하고 메모리 해제를 위한 어떤 코드도 존재 X

    Java Heap의 메모리 해제는 오로지 Garbage Collection을 통해 수행

     

    Opbject Layout

    Heap에 저장되는 Object와 Array는 모두 Header와 Data로 나뉘어져 있음

     

    Hotspot JVM의 Opbject Layout

     

     

    Object는 두 개의 Header

    Array는 세 개의 Header

    헤더 하나당 1word의 크기를 가지고 있음 (32bit - 4byte / 64bit - 8byte)

    First Header - Mark Word, Garbage Collector와 Synchronization 작업을 위해 사용

     

    Hash Code(0)Thread ID(1)AgeBiased(1 bit)Tag

    Lock Record Address

    Monitor Address

    Forwarding Adress 등등

    Mark Word의 헤더1

     

    Biased BitTag상태

    0

    01

    Unlocked

    0

    00

    Light-weight locked

    0

    10

    Heavy-weight locked

    0

    11

    Marked for GC

    1

    01

    Biased / Biasable

    Mark Word의 헤더2 (하위 3bit)

     

    하위 3bit는 Biased Bit가 1이면 Biased Lock 사용

    Synchronization 작업을 수행할 때 Lock을 휙득하기 위한 연산을 수행하지 않고 가볍게 Lock을 휙득한다는 의미

    Biased Lock을 사용하게 되면 Biased Lock로 Synchronization을 수행하는지에 대한 상태 값만 존재

    Biased Bit가 0 →  Biased Lock 사용 X, Tag 별로 4 가지 상태 나타냄

     

    Hash Code 또는 Thread ID는 23 bit 할당 ← Biased Bit와 Tag에 따라 달라짐

    Biased Bit가 1이면 Biased Lock을 획득한 Thread의 ID가 기록

    Biased Bit가 0이고 이전 Synchronization 작업 때 산출 된 Hash Code가 있다면 Tag에 따라 각각 달리 값이 저장

    Light-weight locked - Lock Record Address 

    Heavy-weight locked - Monitor Address 등의 Lock과 관련된 Pointer 정보

    Marked for GC - Forwarding Address의 정보를 Hash Code로 가지고 있게 됨

     

    Age - 6bits로 Young Generation의 Object가 Eden과 Survivor를 넘나든 횟수를 기록

     

    두 번째 Header에는 Method Area의 Class 정보를 가리키는 Reference 정보가 저장 ← 이는 Object와 Array 모두 동일

    Array의 경우 Array Size를 위한 Header가 하나 더 추가

     

    Hotspot JVM의 Opbject Layout

     

     

    VTable

    VTable Structure의 pointer를 가지고 있음

    VTable pointer는 Object Information(OI) Structure 정보 가짐

    OI - Class Name, Debug Data, Object Type, Object Size 등의 정보 포함, GC에 의해 사용됨

     

    Lock Word

     

    Contention bit은 Thread 간에 이 Object 의 lock을 획득하기 위한 경합이 발생하면 On, Base Lock System인 Fat Lock이 사용됨

    Lock Reservation을 사용하는 Reserved Mode에서는 Off

     

    Heap 구조

    HotspotJVM의 Heap 구조

    Generational Heap 구조

    • Young Generation - Eden 영역과 Survivor 영역으로 구성
    • Old Generation - 비교적 참조가 많이 되는 Object 들을 저정하는 공간

    Eden 영역 - Object가 Heap에 최초로 할당 되는 장소

    Eden 영역이 가득차게 되면 참조 여부를 따져 Live Object이면 Survivor 영역으로 참조가 끊어지면 Garbage Object면 그냥 남겨놓음

    모든 Live Object가 survivor 영역으로 넘어가면 Eden 영역을 청소(Scavenge) 함

     

    survivor 영은은 두개로 구성, Live Object를 대피시킬 때는 하나의 Survivor 영역만 사용 ← 이러한 과정을 Minor GC라고 함

    Young Generation에서 Live Object로 오래 살아남으면 Old Generation으로 이동

     

    IBM JVM의 Heap 구조

    1.5 이후 Hotspot과 유사

     

    '프로그래밍 언어 > JAVA' 카테고리의 다른 글

    JAVA 버전별 history  (0) 2020.05.03
    JVM3  (0) 2020.05.02
    JVM  (0) 2020.04.26
    NIO - Buffer  (0) 2020.04.03
    추상 클래스와 인터페이스  (0) 2020.03.29
Designed by Tistory.