자바의 정석 (1) JVM은 무엇이며 자바 코드는 어떻게 실행할까?

Lee DoYeon·2024년 9월 29일
1

자바의 정석

목록 보기
1/3
post-thumbnail

JVM이란 무엇일까?

  • Java Virtual Machine (자바 가상 머신)
  • OS에 종속받지 않고 CPU가 Java를 인식 및 실행할 수 있게 하는 가상 컴퓨터
  • 자바 바이트코드를 CPU가 이해할 수 있게 바이너리코드(기계어)로 바꾸어 주는 머신

컴파일 하는 방법

  • .java 파일을 .class 라는 java bytecode 로 만드는 과정
    Java Compiler는 JDK를 설치하면 javac.exe 라는 실행 파일 형태로 설치된다. JDK의 내부 bin 폴더에 javac.exe로 존재한다.
  • Java Compiler의 javac 명령어를 사용하면 .class 파일을 생성할 수 있다.

실행하는 방법 → (아마 JVM을 실행하는 방법이라고 생각한다)

  • java 명령어로 .class 파일을 실행시킬 수 있다.
    JDK 내부 dir의 /bin 내부에 존재하는 java.exe는 JVM을 구동시키기 위한 명령 프로그램이다.
    ! 정확히는 JRE라고 생각하면 된다. JRE는 JDK 내부에 포함되어 있으니까
    
    JVM이 실행되고, JVM 내부 class loader를 이용해서 `시작 클래스를 생성`하고, `링크`하고, `초기화`하고, `main 메서드를 호출`한다.

바이트코드는 무엇일까?

  • 바이트 코드는 가상 컴퓨터에서 돌아가는 실행 프로그램을 위한 이진 표현법
    자바 바이크 코드는 JVM이 이해할 수 있는 언어로 변환된 자바 소스코드를 의미한다.
    바이크 코드는 다시 실시간 변역기 또는 JIT 컴파일러에 의해 바이너리 코드로 변환된다. (바이러니 코드는 0과 1로 구성된 이진코드)
    즉, CPU가 이해하는 언어는 바이너리 코드, 가상 머신이 이해하는 코드는 바이트 코드이다.

JIT 컴파일러란 무엇이여 어떻게 동작할까?

  • JVM의 표준 구현인 바이트코드를 해석하면 프로그램 실행이 느려짐.

  • JIT 컴파일(just-in-time compliation) 또는 동적 번역(dynamic translation) 이라고 한다.

  • JIT 컴파일러는 프로그램을 실제 실행하는 시점에 기계어로 번역하는 컴파일러이다.

  • 자바는 바이트코드로 한번 컴파일 하는 과정과, 바이트코드를 인터프리터 하는 방식 2가지를 진행한다. 가뜩이나 인터프리너 방식은 소스코드를 런타임시에 한줄 한줄 읽어 들여야 하는 방식 때문에 컴파일 방식보다 느리다.

(1) 컴파일 방식 : 소스코드를 한꺼번에 컴퓨터가 읽을 수 있는 native machine (기계)어로 변환

(2) 인터프리터 방식 : 소스코드를 빌드시에 암것도 하지 않다가, 런타임시에 한줄 한줄 읽어가며 변환, 둘 다 장단점이 있지만, 여기서 중요한건 자바는 컴파일과 인터프리터 방식을 모두 사용한다.

그래서 JIT 컴파일러를 도입하게 된 것 같다. 이미 한번 읽어서 기계어로 변경한 소스코드는 번역하지 않는다.

image

이런식으로 저장소에 저장을 한다는 개념이다. (코드 캐시는 JVM이 JIT 컴파일된 네이티브 코드를 저장하는 메모리 영역입니다. 이 영역은 메서드 영역이나 과는 별개의 공간으로 관리됩니다.) 정확히 다시 말하자면 반복되는 코드를 모두 컴파일러로 컴파일 시키는 것이다. 인터프리터의 역할을 보조한다고 생각하면 될듯 싶다.

JVM 구성 요소

image

  • java 명령어의 인자로 지정한 설정 옵션에 맞게 JVM이 실행되고 Class Loader를 이용해서 initial class를 create하고, initial class를 link하고, initialize하고, main 매서드를 호출한다.

  • 용어 정리

    • initial class: JVM 구현에 따라 다를 수 있지만 일반적으로 main 메서드를 포함하는 클래스로서 java 명령어의 인자로 지정되는 클래스 (JVM 스펙 참고)
    • create (a class or interface): 해당 클래스나 인터페이스의 바이트코드를 로딩해서 JVM이 할당한 메모리(Method Area, 메서드 영역)에 construction하는 것 (JVM 스펙 참고)
    • link (a class or interface): 해당 클래스나 인터페이스의 바로 위 수퍼클래스나 수퍼인터페이스, 또는 배열일 경우 배열의 원소인 클래스나 인터페이스를 확인(verify)/준비(prepare)하고, 심볼릭 참조를 해석(resolve)해서 JVM에서 실행될 수 있는 상태로 만드는 것 (JVM 스펙 참고)
    • initialize (a class or interface): 해당 클래스나 인터페이스의 class or interface initialization method를 실행하는 것 (JVM 스펙 참고)
  • JVM의 구성요서는 크게 3가지

    • Class Loader

      • 클래스를 읽어오는 시스템 구조. 로딩 → 링크 → 초기화

        image

- Runtime Data Area
    - Stack
    - PC Register
    - Native Method Stack
    - Heap
        - 힙은 인스턴스화 된 모든 클래스 인스턴스와 배열을 저장, 객체를 저장하게 되는데, 모든 JVM 스레드에 공유 되는 공유 자원 이다. 힙에 저장된 할당된 메모리 회수 권한은 무조건 가비지 컬렉터(Garbage Collector)에 의해서만 회수가 가능하다.
    - Method
        - 런타임 상수 풀, 필드와 메서드 정보, 클래스 수준의 정보, 메서드 테이블이 저장되는 곳.
        - 힙과 메서드 영역을 분리하였지만, jvm 스펙에서는 메소드 영역이 논리적으로 힙의 일부여서 가비지 컬렉션에 대상이 된다고 하지만, 강제적으로 메소드의 영역의 위치에 대해서 논하지 않는다고 한다. 즉, JVM 을 회사를 만드는 회사마다
- Excution Engine
    - Interpreter
    - JIT Compiler
    - Garbage Collector

JDK와 JRE의 차이

  • JDK : 자바 개발도구(java devlopment kit), JRE + 개발에 필요한 실행파일

    • JDK 내부 dir의 /bin 내부에 존재하는 java.exe는 JVM을 구동시키기 위한 명령 프로그램이다.
  • JRE : 자바 실행환경(java runtime environment), JVM + 클래스 라이브러리

  • JDK를 통해서 byte code를 생성 JRE에게 토스
    JRE를 사용해서 byte code를 java 명령어로 실행하게 된다.
    JVM이 ‘실행’단계를 걸친다
    크게 차이를 구분짓기보다 JDK 내부에 JRE가 포함되어 있다.

    image

profile
I can do this all day

0개의 댓글