관리 메뉴

개발그래머

[자바스터디 1주차] JVM은 무엇이며 자바 코드는 어떻게 실행하는 것인가 본문

Java

[자바스터디 1주차] JVM은 무엇이며 자바 코드는 어떻게 실행하는 것인가

임요환 2023. 4. 24. 22:39

목표

  • 자바 소스 파일(.java)을 JVM으로 실행하는 과정 이해하기
  • 컴파일타임과 런타임을 구분하기

학습할 것

  • JVM이란 무엇인가
  • 컴파일 하는 방법
  • 실행하는 방법
  • 바이트코드란 무엇인가
  • JIT 컴파일러란 무엇이며 어떻게 동작하는지
  • JVM 구성 요소
  • JDK와 JRE의 차이

JVM이란 무엇인가

  • Java Virtual Machine
  • 운영체제와 하드웨어에 독립적으로 동작하며 자바 코드를 실행하기 위해 필요한 라이브러리 및 기능을 제공함
  • 자바 바이트코드를 실행하는 역할을 수행함

컴파일 하는 방법

  • javac(java compiler)를 사용하여 컴파일
  • 일반적으로 상위버전으로 컴파일된 클래스파일은 하위버전에서 동작하지 않지만 컴파일 시 -target 옵션을 설정하여 호환 가능하게 만들 수 있음
  • 버전이 올라갈수록 javac의 성능도 올라가므로 버전을 낮춰서 호환시켜야 하는 상황이 아니면 하지 않는게 좋음
  • java 파일을 컴파일시키면 .class확장자를 가진 자바 바이트코드가 만들어짐
  • javap -c Main.class 를 사용하여 클래스 파일을 OP(operation code)코드를 사용하여 읽기 쉽게 보여줌
//상위 버전으로 컴파일된 클래스파일을 하위 버전에서 동작시 발생하는 에러
//에러 메시지를 읽어라
Error: A JNI error has occurred, please check your installation and try again
Exception in thread "main" java.lang.UnsupportedClassVersionError: Main has been compiled by a more recent version of the Java Runtime (class file version 57.0), this version of the Java Runtime only recognizes class file versions up to 52.0

실행하는 방법

  • Main.class파일 실행 -> java Main

Java 파일 실행 과정

  1. 소스코드 작성 - .java 확장자를 가지는 텍스트 파일 작성
  2. 컴파일 - javac를 사용하여 .class확장자를 가지는 바이트코드로 변환
  3. 클래스 로딩 - JVM 클래스 로더를 사용하여 필요한 클래스 파일을 로드, 로드된 클래스 파일은 런타임 데이터 영역에 저장
  4. 바이트코드 검증 - 로드된 바이트코드를 검증(올바른 형식인지, 오류가 있는지 등)
  5. 실행 엔진에 의한 바이트코드 실행 - 인터프리터로 실행하거나, JIT 컴파일러를 사용하여 네이티브 코드로 변환하여 실행

바이트코드란 무엇인가

  • JVM이 이해할 수 있는 언어(바이너리 코드 2진수로 되어있음)
  • 바이트코드는 기계어가 아니기 때문에 OS에서 바로 실행할 수 없음
  • 자바 소스 코드를 컴파일하여 생성되는 중간 형식의 코드로, 기계어보다는 약간 더 추상화된 형태
  • JVM이 해독할 수 있는 바이트코드만 만들 수 있다면 kotlin, groovy 등 다른 언어들을 사용해도 됨

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

  • Just In Time 컴파일러
  • 반복되는 코드, 자주 사용되는 코드를 JIT 컴파일러가 자바 바이트코드를 기계어로 변환해서 컴파일한 후 JVM Runtime 영역에 캐싱하여 재사용함
  • 기계어로 인터프리터가 해석할 필요 없이 기계어가 바로 실행을 하여 속도가 빨라짐
  • 인터프리터는 자바 바이트코드를 한줄 씩 실행, 전체 성능면에서 불리함
  • 프로그램을 실행하는 시점에 동작함
  • JVM은 내부적으로 해당 메서드가 얼마나 자주 수행되는지 체크하고 일정 정도를 넘을 때만 컴파일 수행

JVM 구성 요소

  1. Class Loader
    • 클래스 로더는 JVM이 실행할 클래스 파일을 로드함
    • 클래스 파일을 찾고, 검증하고, JVM이 사용할 수 있는 형식으로 반환함
  2. Execution Engine
    • 클래스 파일에서 바이트코드를 실행함
    • 바이트코드를 인터프리터로 실행하거나, JIT 컴파일러를 사용하여 네이티브 코드로 변환하여 실행함
    • GC(Garbage Collector): 자동으로 더 이상 사용되지 않는 객체를 메모리에서 제거하여 메모리 누수를 방지함
  3. Runtime Data Area
    • JVM이 실행하는 Java 프로그램에 필요한 데이터를 저장하는 메모리 공간
    • 메소드 영역, 힙 영역, 스택 영역 등이 있음
    • 메소드 영역 : 클래스 파일에서 로드된 클래스, 인터페이스, 메소드, 상수 등의 정보를 저장
    • 힙 영역 : 객체 인스턴스가 생성되는 메모리 공간, 가비지 컬렉터를 사용하여 힙 영역에서 더 이상 사용되지 않는 객체를 제거
    • 스택 영역 : 메소드 호출에 따라 생성되는 지역 변수, 매개 변수, 리턴 값 등을 저장, 각 스레드마다 별도로 존재함
  4. Native Method Interface
    • Java 코드에서 C, C++, 어셈블리 등의 네이티브 코드를 호출할 수 있는 인터페이스를 제공
    • Java 언어로 작성할 수 없는 시스템 라이브러리 및 하드웨어를 사용할 수 있음

JDK와 JRE의 차이

JDK(Java Development Kit) = 자바 개발 도구 = 자바 애플리케이션을 개발하는 데 필요한 모든 도구와 라이브러리를 포함함  
JRE(Java Runtime Environment) = 자바 실행 환경 = 자바 애플리케이션을 실행하는 데만 필요함
  • JDK > JRE
  • JDK는 JRE를 포함하여 추가로 Javac, Jar, Javadoc, 디버깅 도구, 프로파일링 도구, 테스트 도구 등을 제공함
  • java9부터는 JDK만 제공