Java 컴파일 과정

Travel·2023년 8월 18일

Java

목록 보기
2/5

자바가 운영체제에 독립적일 수 있는 이유는 JVM 덕분이다.

Java 컴파일 과정

  1. 개발자가 자바 소스코드(.java)를 작성

  2. 자바 컴파일러(Java Compiler)가 자바 소스파일을 컴파일

    • 이때 나오는 파일은 자바 바이트 코드(.class)파일로 아직 컴퓨터가 읽을 수 없는 자바 가상 머신이 이해할 수 있는 코드
  3. 컴파일된 바이트 코드를 JVM의 클래스로더(Class Loader)에게 전달

  4. 클래스 로더는 동적로딩(Dynamic Loading)을 통해 필요한 클래스들을 로딩 및 링크하여 런타임 데이터 영역(Runtime Data area), 즉 JVM의 메모리에 올린다.

    클래스 로더 세부 동작

    1. 로드 : 클래스 파일을 가져와서 JVM의 메모리에 로드

    2. 검증 : 자바 언어 명세(Java Language Specification) 및 JVM 명세에 명시된 대로 구성되어 있는지 검사

    3. 준비 : 클래스가 필요로 하는 메모리를 할당 (필드, 메서드, 인터페이스 등등)

    4. 분석 : 클래스의 상수 풀 내 모든 심볼릭 레퍼런스를 다이렉트 레퍼런스로 변경

    5. 초기화 : 클래스 변수들을 적절한 값으로 초기화 (static 필드)

  5. 실행엔진(Execution Engine)은 JVM 메모리에 올라온 바이트 코드들을 명령어 단위로 하나씩 가져와서 실행한다. 이때, 실행 엔진은 두가지 방식으로 변경

    인터프리터

    • 바이트 코드 한 줄 씩 해석하며 실행
    • 미리 컴파일된 바이트코드를 직접 실행하지만, 코드 실행 시간이 느릴 수 있음
    • 코드 실행 중에 최적화가 제한적

    JIT 컴파일러(Just-In-Time Compiler)

    • 바이트코드를 기계어로 컴파일하므로 실행 속도가 인터프리터보다 훨씬 빠름
    • 런타임 중에 최적화 수행 가능하여 실행 속도를 향상시킴
    • 자주 사용되는 코드를 컴파일하여 캐시에 저장하므로, 반복적으로 사용되는 코드에 대한 성능 향상 효과를 누릴 수 있음

    Garbage Collector

    • 더이상 참조되지 않는 메모리 객체를 모아 제거하는 역할을 수행
    • 일반적으로 자동으로 실행되지만, 수동으로 실행하기 위해 System.gc()를 사용할 수 있음(다만, 실행이 보장되지는 않음)
  6. 해석된 바이트 코드는 메모리 영역에 배치되어 실질적인 수행이 이루어지며, 실행 과정 속 JVM은 필요에 따라 스레드 동기화나 가비지 컬렉션 같은 메모리 관리 작업을 수행

    Runtime Data Areas
    JVM이 운영체제 위에서 실행되면서 할당받는 메모리 영역이며 총 5가지 영역으로 나누어짐
    (이 중에 힙과 메서드 영역은 모든 스레드가 공유해서 사용함)

    PC 레지스터 : 스레드가 어떤 명령어로 실행되어야 할지 기록하는 부분(JVM 명령의 주소를 가짐)

    스택 Area : 지역변수, 매개변수, 메서드 정보, 임시 데이터 등을 저장

    네이티브 메서드 스택 : 실제 실행할 수 있는 기계어로 작성된 프로그램을 실행시키는 영역

    힙 : 런타임에 동적으로 할당되는 데이터가 저장되는 영역. 객체나 배열 생성이 여기에 해당함
    (또한 힙에 할당된 데이터들은 가비지컬렉터의 대상이 됨. JVM 성능 이슈에서 가장 많이 언급되는 공간임)

    메서드 영역 : JVM이 시작될 때 생성되고, JVM이 읽은 각각의 클래스와 인터페이스에 대한 런타임 상수 풀, 필드 및 메서드 코드, 정적 변수, 메서드의 바이트 코드 등을 보관함

    출처
    링크

0개의 댓글