ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • JVM Run-Time Data Area
    개발/Java 2021. 4. 6. 16:50

    이전에 JVM에 대해 정리한 내용이 있는데, 좀 더 추가할 내용이 있어서 작성하였다.

    (Constant Pool, Static은 어디에, Heap, Garbage Collection 등..)

    Live-Study 1주차 정리내용 - JVM

    soongjamm.tistory.com/95

     

    [live-study] 1: JVM은 무엇이며 자바 코드는 어떻게 실행하는 것인가.

    백기선님이 진행하시는 live-study 1주차 과제 1주차 과제 목표 자바 소스 파일(.java)을 JVM으로 실행하는 과정 이해하기. 학습할 것 JVM이란 무엇인가 컴파일 하는 방법 실행하는 방법 바이트코드란

    soongjamm.tistory.com

     


    • JVM
    • JVM과 추상화
    • Run-Time Data Areas
    • static 변수는 어디에 저장될까?
      • Heap 자세히 보기

     

    JVM (Java Virtual Machine)

    바이트코드로 컴파일된 Java 코드를 실행시켜주는 가상 머신이다.

    어떤 환경에서 작성했던 Java 코드는 JVM을 통해 각각의 플랫폼(운영체제)에서 프로그램을 실행할 수 있다. 이것을 두고 Java는 플랫폼에 독립적 이라 한다.

    물론 각각의 환경에서 JRE를 설치해야하지만 한번만 설치하면 계속해서 사용할 수 있다. 이것을 Write Once Run Anywhere 라고 한다.

    • JVM과 별도로 Java Compiler를 이용해서 .java 를 바이트코드로 컴파일한다.
    • 바이트코드는 .class 파일이다.

     

    JVM과 추상화

    JVM이 운영체제에 독립적으로 동작한다는건 알고 있었는데, '그냥 그런가보다' 생각했지 가슴에 와닿진 않았다.

    같은 운영체제 안에서, 버전도 같은데 왜 자바 종류는 이렇게 다양한지도 의문이었다.

    • oracle JDK
    • AdoptOpen JDK
    • RedHatOpen JDK
    • ...등등

    최근에 객체지향을 공부해서 추상화를 이해하게 된 후, 오라클 공식문서를 보니 느낌이 달랐다.

    This document specifies an abstract machine. It does not describe any particular implementation of the Java Virtual Machine.

    To implement the Java Virtual Machine correctly, you need only be able to read the class file format and correctly perform the operations specified therein. Implementation details that are not part of the Java Virtual Machine's specification would unnecessarily constrain the creativity of implementors. For example, the memory layout of run-time data areas, the garbage-collection algorithm used, and any internal optimization of the Java Virtual Machine instructions (for example, translating them into machine code) are left to the discretion of the implementor.

    자바 버전이나 운영체제에 따라 구현은 달라질 수 있다.

    자바를 사용하면 GC(garbage-collection)가 메모리를 관리하고 run-time data areas가 존재하는 것도 맞지만,

    GC가 어떤 알고리즘을 사용해서 메모리를 정리하는지와 run-time data areas가 어떤 레이아웃을 가졌는지는 내가 어떤 구현체를 사용하느냐에 따라 달라지는 것이다.

    서로 다른 구현을 할 수 있기 때문에 벤더사들은 효율적으로 Java를 구현하고 유료로도 배포하고 하는게 아닌가 싶다. (개인적인 생각)

     

    Run-Time Data Areas

    JVM은 하나의 애플리케이션이 여러개의 쓰레드를 갖는 것을 허용한다. 그래서 main() 쓰레드가 생성되면 GC 쓰레드 외 여러가지 쓰레드가 부가적으로 생성된다.

    이 때 각각의 쓰레드는 Run-Time Data Areas 를 갖고 있거나 공유하고 있다.

    • 이름 그대로 프로그램 실행 중에 데이터를 저장하는 영역이다.

    Run-Time Data Areas는 아래 영역들로 세분화할 수 있다.

     

    PC register

    현재 실행중인 명령의 주소값을 가지고 있다. (Method Area의 메모리 주소)

    만약 실행중인 명령이 Native 메소드면 PC register는 undefined이다.

    • Native 메소드는 C나 C++ 등 다른 언어로 작성된 메소드를 말한다.

     

    Java Virtual Machine Stacks

    쓰레드 한 개에 하나씩 생성되는 스택이다. 스택에는 Frame 들을 담고 있다. 이 Frame은 메소드가 호출되면 생성되고(push) 명령을 마치치거나 예외가 발생하면 종료(pop) 된다.

    • Frame은 메소드의 지역변수, 리턴 값 등을 저장하고 있다.

    JVM Stacks 관련해서 두 가지 예외가 발생할 수 있다. :

    • 쓰레드에 더이상 Frame을 저장할 공간이 없을 때(메소드를 더이상 호출할 수 없을 때) StackOverflowError 가 발생한다.
      • 이 경우 JVM -Xss 옵션으로 스택 사이즈를 조절해서 에러를 피하는 방법이 있다.
    • JVM Stacks 영역에 너무 많은 쓰레드가 존재하는 경우 OutOfMemoryError 가 발생한다.

    JVM Stacks ( http://www.herongyang.com/JVM/Stack-Overflow-What-Is-JVM-Stack.html )

     

    Heap

    JVM 쓰레드간 공유되는 영역으로 클래스의 인스턴스들이 할당되는 공간이다. (new 키워드로 생성된 객체들)

    더이상 참조되지 않는 인스턴스들은 Garbage Collector에 의해서 회수된다. (회수 전략은 jdk 마다 다를 수 있다.)

    • 허용된 공간을 초과하면 OutOfMemoryError 가 발생한다.

     

    Method Area

    JVM 쓰레드간 공유되는 영역이고 논리적으로 Heap의 일부분이며 클래스의 구조를 저장한다.

    • 클래스 이름
    • Run-Time Constant Pool
    • 필드 데이터
    • 생성자 및 메소드 데이터 (이름, 파라미터 등)
    • 마찬가지로 요청된 할당을 처리할 공간이 없다면 OutOfMemoryError 가 발생한다.

     

    Run-Time Constant Pool

    JVM은 런타임에 사용되는 리터럴을 .class 파일 내에 존재하는 constant_pool 이라는 테이블을 통해 참조한다.

    • 예를들어 다음과 같은 빈 클래스가 있다고 하자
    public class Main {
        public void main(String[] args) {
    
        }
    }
    • 바이트코드를 확인해보면 아래와 같이 constant_pool 이 만들어진다.
    public class Main
      minor version: 0
      major version: 58
      flags: (0x0021) ACC_PUBLIC, ACC_SUPER
      this_class: #7                          // Main
      super_class: #2                         // java/lang/Object
      interfaces: 0, fields: 0, methods: 2, attributes: 1
    Constant pool:
       #1 = Methodref          #2.#3          // java/lang/Object."<init>":()V
       #2 = Class              #4             // java/lang/Object
       #3 = NameAndType        #5:#6          // "<init>":()V
       #4 = Utf8               java/lang/Object
       #5 = Utf8               <init>
       #6 = Utf8               ()V
       #7 = Class              #8             // Main
       #8 = Utf8               Main
       #9 = Utf8               Code
      #10 = Utf8               LineNumberTable
      #11 = Utf8               main
      #12 = Utf8               ([Ljava/lang/String;)V
      #13 = Utf8               SourceFile
      #14 = Utf8               Main.java
    {
      public Main();
        descriptor: ()V
        flags: (0x0001) ACC_PUBLIC
        Code:
          stack=1, locals=1, args_size=1
             0: aload_0
    ...(생략)

    같이 참고하면 좋을 내용 : String Pool

     

    Native Method Stacks

    native 메소드를 위해 사용되는 영역이다.

    static 변수는 어디에 저장될까?

    static 변수가 어디에 저장되는지 알아보기전에 heap영역을 살펴보자.

    (결론부터 말하자면 Java7 까지는 PermGen, 8부터는 Metaspace)

    Heap 내부

    Heap 영역에는 **Young Generation (Nursery)**와 Old Generation이 존재한다.

    • new 키워드로 생성된 객체는 최초에 모두 Young Generation에 위치한다. 메모리가 가득 차면 Garbage Collection을 진행하고 이를 Minor Garbage Collection 이라고 한다.
    • Garbage Collection에게서 여러 라운드를 살아남은 객체는 Old Generation으로 옮겨진다. 이곳도 메모리가 가득하면 Garabage Colelction을 진행하고 이를 Major Garbage Collelction 이라고 한다.

    출처 :  https://www.geeksforgeeks.org/metaspace-in-java-8-with-examples/

    • 위의 그림처럼 힙에 Young/Old Generation가 존재하고 이를 벗어나 PermGen 이 존재한다.

    PermGen

    • 위에서 나왔던 Method Area는 PermGen의 일부분이고, 이 곳에 static 메소드나 변수가 존재하며 클래스 정의들도 존재한다.
    • 근데 이 PermGen은 공간이 한정적이고 자동으로 증가시켜주지 않아서 OutOfMemoryError 를 발생시킬 위험이 있다.

    Metaspace

    • 그래서 Java8 부터는 PermGen이 완전히 사라지고 Metaspace가 나타났는데, 이는 자동으로 증가시켜줘서 OOME 위험이 줄어들었다.
    • Metaspace는 JVM memory가 아닌, native memory에 위치하고 있다.

    레퍼런스

    http://www.herongyang.com/JVM/Stack-Overflow-What-Is-JVM-Stack.html

    https://blog.jamesdbloom.com/JVMInternals.html#jvm_system_threads

    https://stackoverflow.com/questions/50163218/is-method-area-still-present-in-java-8

    http://blog.breakingthat.com/2018/12/21/java-constant-pool과-string-pool/

    PermGen vs Metaspace : https://www.baeldung.com/java-permgen-metaspace#:~:text=Simply put%2C Metaspace is a,region grows automatically by default.

    댓글

Designed by Tistory.