1회차. JVM은 무엇이며 자바 코드는 어떻게 실행하는 것인가

KIMA·2023년 1월 8일
0
post-thumbnail

목표

자바 소스 파일(.java)을 JVM으로 실행하는 과정 이해하기

학습할 것

JVM이란 무엇인가


JVM이란

Write once, run anywhere (한 번 작성하면 어디서든 실행된다)

  • JVM(Java Virtual Machine) : OS 독립적으로 자바를 실행하기 위한 가상 컴퓨터
  • 컴파일된 바이너리 코드(.class)를 실행할 때, 프로그램이 실행되는 OS에 맞게 컴퓨터가 해석할 수 있는 기계어로 변환해준다.
  • 자바로 작성된 애플리케이션은 모두 JVM에서만 실행된다.
  • 장점
    • 자바 애플리케이션은 일반 애플리케이션과 달리 JVM하고만 상호작용을 하기 때문에 OS와 하드웨어에 독립적이다.
      • 따라서, 다른 OS에서도 프로그램의 변경없이 실행이 가능하다.
      • 하지만, 일반 애플리케이션은 OS와 바로 맞붙어 있기 때문에 다른 OS에서 실행시키기 위해서는 애플리케이션을 해당 OS에 맞게 변경해야한다.
        • 예) C언어는 OS의 종류가 달라지면 해석하지 못한다.
      • 단, JVM은 OS에 종속적이므로 해당 OS에서 실행가능한 JVM이 필요하다.
    • Garbage Collection이 있어 개발자가 메모리 할당, 해제를 신경 쓰지 않아도 된다.
      • 단점 : 성능
  • 단점 : 하드웨어에 맞게 완전히 컴파일된 상태가 아니고 실행 시에 해석되기 때문에 속도가 느리다.
    • 하지만 요즘엔 JIT 컴파일러와 향상된 최적화 기술이 적용되어서 속도의 격차를 많이 줄였다.

자바 소스 파일을 컴파일 하는 방법


javac *.java

  • 자바 소스파일인 .java를 컴파일하면 바이트코드인 .class파일로 변환된다.

  • 자바 컴파일러인 javac.exe는 JDK 설치 후 bin 폴더에 존재한다.

  • javac의 옵션

    옵션설명예제기본값
    -classpath, -cp클래스패스(실행할 클래스의 위치) 지정javac -cp "/Users/home/A.java"현재 디렉토리
    -d어디에 클래스파일을 생성할지 지정javac -d "/User/home/path"현재 디렉토리
    -encoding소스 파일에 사용된 인코딩 지정javac -encoding "utf-8" A.java
    -g모든 디버깅 정보를 출력javac -g
    -verbose컴파일러가 진행하는 작업을 모두 출력javac -verbose
    -sourcepath소스파일 위치 지정javac -sourcepath "/User/home/path”
    -source소스파일 자바 버전 지정javac -source 1.8
    -target타겟파일 자바 버전 지정javac -target 1.8
  • 높은 버전의 클래스파일을 낮은 버전의 JVM으로 실행하고자 하는 경우 에러가 발생한다.

    • 해결책
      • 첫째, -target 옵션을 통해 낮은 버전의 클래스파일로 컴파일
        • 단, 높은 버전에서 새로 생긴 기능을 사용했다면 컴파일 오류가 발생한다.
        • 만약, .class 파일만 가지고 있다면 두번째 방법을 이용하자.
      • 둘째, 현재 자바 버전을 최신버전으로 업그레이드
    • 반대의 경우에는 자바가 하위 버전에 대한 호환성을 보장하므로 에러가 발생하지 않는다.

바이트코드란 무엇인가


  • 바이트코드 : JVM이 이해할 수 있는 언어인 컴파일된 자바코드(.class)를 의미한다.
  • 컴파일된 자바코드의 명령어(OP) 크기가 1바이트라서 자바 바이트코드로 불린다.
  • 0과 1로 구성된 바이너리 코드이다.
    • javap -c *.class를 통해 자바 바이트코드를 사람이 해석할 수 있는 형태로 변환할 수 있다.
  • 바이트코드는 다시 실시간 번역기 또는 JIT 컴파일러에 의해 CPU가 이해할 수 있는 바이너리 코드(=이진 코드)로 변환된다.

    ❓ 기계어란?

    • CPU가 이해하는 0과 1로 이루어진 바이너리 코드이다.
    • 기계어가 이진코드로 이루어졌을 뿐 이진코드가 기계어인 것은 아니다.

바이트코드를 JVM으로 실행하는 방법


java *.class

  • JVM을 실행시키기 위한 프로그램인 .java.exe는 JDK 설치 후 bin 폴더에 존재한다.

JIT 컴파일러란 무엇이며 어떻게 동작하는지


  • JIT(Just-In-Time) 컴파일러 : 프로그램을 실제 실행하는 시점에 바이트코드를 하드웨어의 기계어로 바로 변환해주는 컴파일러
  • 동적 번역이라고도 불린다.
  • 인터프리터 방식의 단점을 보완하기 위해 도입되었다.
    • 인터프리터 방식으로 실행하다가 적절한 시점에 바이트코드 전체를 컴파일하여 기계어로 변경하고, 이후에는 더 이상 인터프리팅 하지 않고 기계어로 직접 실행하는 방식이다.
  • 장점 : 기계어는 캐시에 보관하기 때문에 한 번 컴파일된 코드는 빠르게 수행하게 된다.
  • 단점 : 인터프리팅에 비해 시간이 훨씬 많이 소모되므로 한 번만 실행되는 코드라면 컴파일하지 않고 인터프리팅하는 것이 유리하다.
    • 따라서, JIT 컴파일러를 사용하는 JVM들은 내부적으로 해당 메서드가 얼마나 자주 수행되는지 체크하고 일정 정도를 넘을때에만 컴파일을 수행한다.

JVM 구성 요소


JVM의 구조

  • 클래스 로더
    • 런 타임시 처음 참조된 클래스(.class)를 동적으로 메모리상의 JVM으로 로드하고 링크하는 역할
    • JVM 내의 런타임 데이터 영역에 바이트코드를 배치한다.
  • 실행 엔진
    • 메모리에 로드된 바이트코드를 실행시키는 역할
    • 구성 요소 각각은 스레드로 만들어져 동시에 수행된다.
      • 하지만 GC를 수행하는 동안 다른 모든 Thread는 일시정지된다.
        • 이로인한 문제를 조심할 것
    • 구성 요소
      • 인터프리터
        • 실행 엔진은 자바 바이트코드를 명령어 단위로 읽어서 실행한다.
        • 단점 : 한 줄씩 수행하여 속도가 느리다.
      • JIT 컴파일러
        • 인터프리터 방식으로 실행하다가 적절한 시점에 바이트코드 전체를 컴파일하여 기계어로 변경하고, 이후에는 더 이상 인터프리팅 하지 않고 기계어로 직접 실행하는 방식이다.
      • 가비지 콜렉터
        • 더이상 사용되지 않는 인스턴스를 찾아 메모리에서 삭제한다.
  • 런타임 데이터 영역
    런타임 데이터 영역
    • 프로그램을 수행하기 위해 OS에서 할당받은 메모리 공간
    • 구성 요소
      • PC(Program Counter) Register
        • 스레드가 시작될 때마다 생성되는 공간으로, 스레드마다 하나씩 존재한다.
        • 현재 실행된 스레드의 메소드가 PC Register에 JVM 명령 주소를 저장한다. (JVM 명령은 1 byte의 opcode와 0개 이상의 피연산자로 구성)
          • 이때, 현재 실행된 스레드의 메소드가 네이티브 메소드라면 바이트코드의 명령어가 없기 때문에 PC Register가 비어있거나 정의되지 않는다.
      • JVM Stack
        • 프로그램 실행과정에서 임시로 할당되었다가 메소드를 빠져나가면 바로 소멸되는 특성의 데이터를 저장하는 영역
        • 저장하는 요소 : Stack Frameㄹ
          • 로컬 변수
          • 일부 실행 결과
          • 메소드 호출 또는 반환
        • 스레드마다 JVM Stack이 존재하며, 스레드가 생성될 때마다 같이 생성된다.
      • Native Method Stack
        • Java가 아닌 다른 언어(C, C++, 어셈블러 등)로 작성된 코드를 위한 공간
          • Java는 하드웨어를 직접 제어하는 기능이 없으므로 C언어 같은 다른 언어의 기능을 빌려 사용한다.
          • 네이티브 방식의 메소드(다른 언어로 작성된 코드)가 실행되는 경우 Native Method Stack을 이용한다.
        • JNI(Java Native Interface) 기술로 네이티브 메소드들이 바이트 코드로 변환 되면서 저장하게 된다.
        • 자바 프로그램이 컴파일되어 생성되는 바이트코드가 아닌 실제 실행할 수 있는 기계어로 작성된 프로그램을 실행시키는 영역
      • Method Area (= Class Area, Static Area)
        • 클래스 정보를 처음 메모리 공간에 올릴 때 초기화되는 대상을 저장하기 위한 메모리 영역
        • 저장되는 데이터
          • 멤버 변수 : 멤버변수의 이름, 데이터 타입, 접근 제어자에 대한 정보
          • 메소드 : 메소드의 이름, 리턴타입, 매개변수, 접근 제어자에 대한 정보
          • 타입 : class인지 interface인지의 여부 저장. Type의 속성, 전체 이름, super 클래스의 전체 이름. (interface이거나 object인 경우 제외된다. 이건 Heap에서 관리한다.)
        • Runtime Constant Pool : 별도의 관리영역으로서 상수 자료형을 저장하여 참조하고 중복을 막는 역할을 수행한다.
      • Heap
        • 객체를 저장하는 가상 메모리 공간
        • Class Area에 있는 클래스들을 객체로 생성한다.
        • GC에 의해 관리되는 영역이다.
        • 구성요소
          • Permanent Generation
            • 생성된 객체들의 정보의 주소값이 저장된 공간
            • 클래스 로더에 의해 로드되는 클래스, 메소드 등에 대한 Meta 정보가 저장되는 영역이고 JVM에 의해 사용된다.
            • Reflection을 사용하여 동적으로 클래스가 로딩되는 경우에 사용된다.
              • 객체를 통해 클래스의 정보를 분석해 내는 프로그래밍 기법
              • 구체적인 클래스 타입을 알지 못해도, 컴파일된 바이트코드를 통해 역으로 클래스의 정보를 알아내어 사용할 수 있다는 뜻이다.
          • New/Young Generation(Minor GC)
            • 추후 가비지 콜렉터에 의해 사라질 인스턴스들이 있는 영역
            • 생멍주기가 짧은 객체가 저장됨
            • 구성요소
              • Eden : 객체들이 최초로 생성되는 공간
              • Survivor0, 1: Eden에서 참조되는 객체들이 저장되는 공간
            • Eden 영역에 객체가 가득차게 되면 첫번째 GC가 발생한다.
              • Eden 영역에 있는 값들을 Survivor1 영역에 복사하고 이 영역을 제외한 나머지 객체를 삭제한다.
          • Old Generation(Major GC)
            • 추후 가비지 콜렉터에 의해 사라질 인스턴스들이 있는 영역
            • New/Young Area에서 일정시간 참조되고 있는, 살아남은 객체들이 저장되는 공간으로 생멍주기가 긴 객체가 저장된다.
            • Minor GC에 비해 속도가 느리다.

JDK와 JRE의 차이


JDK와 JRE의 차이

  • JDK(Java Development Kit) : JRE + 도구(컴파일러(javac), 자바 디버거(jdb), javadoc, 서로 연관있는 클래스들을 묶어주는 jar, java 등)
    • 자바를 사용하기 위해 필요한 모든 기능을 갖춘 자바용 SDK(Software Development Kit)이다.
  • JRE(Java Runtime Environment) : JVM + 자바 클래스 라이브러리

최종 정리

최종 정리

Reference
1. [JAVA] JVM이란? 개념 및 구조 (JDK, JRE, JIT, 가비지 콜렉터...)
2. 자바의 정석 3rd Edition, 남궁성 지음
3. [Java-Live-Study] 1주차 - 자바 소스 파일(.java)을 JVM으로 실행하는 과정 이해
4. JVM 메모리 구조 정리

profile
안녕하세요.

0개의 댓글