본문 바로가기
Back-End/Java

Java(1)

by newny 2023. 3. 13.
반응형

JVM 동작 원리

자바 언어로 작성된 프로그램을 실행하기 위한 가상 머신.
이로인해 자바 언어로 작성된 프로그램은 운영체제나 하드웨어와 상관없이 동일한 방식으로 실행될 수 있음.

 

1. 자바 코드를 바이트 코드로 컴파일 (javac.exe)하여 클래스 파일 형태(.class)로 저장

  • 컴파일
    • 프로그램에서 "컴파일"은 소스 코드를 컴퓨터가 이해할 수 있는 기계어로 번역하는 과정을 의미한다. 컴파일러(Compiler)는 소스 코드를 입력으로 받아 기계어로 변환하고, 이를 목적 파일(Object File)로 저장한다. 이 과정에서 오류가 발생할 경우, 컴파일러가 오류 메시지를 출력하고 컴파일을 중단한다.
    • 자바에서는 소스 코드가 컴파일러에 의해 바이트 코드로 컴파일된다. 바이트 코드는 JVM이 이해할 수 있는 중간 코드로, 클래스 파일에 저장된다. 이 과정에서는 다음과 같은 단계가 수행된다.
    • 구문 분석(Syntax Analysis): 소스 코드를 토큰으로 분할하고, 구문 구조를 검사한다.
    • 의미 분석(Semantic Analysis): 컴파일러는 식별자(Identifier)와 타입(Type)을 검사하고, 이에 대한 정보를 생성한다. 컴파일 단계에서 생성된 바이트 코드는 이후 JVM에서 로딩, 링크, 실행되어 프로그램이 동작한다.
    • 코드 생성(Code Generation): 검사된 소스 코드를 바이트 코드로 변환한다. 이때, 바이트 코드는 JVM에서 실행 가능한 형태로 변환된다.
    • 컴파일 단계에서 생성된 바이트 코드는 이후 JVM에서 로딩, 링크, 실행되어 프로그램이 동작한다.
  • 목적 파일(Object file)
    • 컴파일러는 소스 코드를 목적 파일로 변환할 때, 여러 개의 객체를 생성한다. 이러한 객체들은 실행 파일을 만들기 위해 링커(Linker)에 의해 결합된다. 목적 파일은 컴파일러가 생성하는 중간 단계의 결과물로, 여러 목적 파일을 링크하여 실행 파일을 만들어내는데 사용된다.목적 파일은 일반적으로 실행 파일의 크기를 줄이기 위해 사용되는 코드 최적화 등의 다양한 기술을 적용할 수 있다. 목적 파일은 실행 파일을 만들기 위한 중간 단계의 결과물이기 때문에, 실행 파일의 크기와 성능에 직접적인 영향을 미친다.
    • 목적 파일은 일반적으로 컴파일러에 의해 생성되며, 실행 파일을 만들기 위해 다른 목적 파일과 링크된다. 따라서, 목적 파일은 링커에 의해 결합되는 코드와 데이터를 포함하고 있다.
    • 목적 파일(Object file)은 컴파일러가 소스 코드를 컴파일하여 생성하는 바이너리 형태의 파일이다. 목적 파일은 여러 가지 객체(Object)들을 포함하고 있으며, 이 객체들은 프로그램의 실행을 위한 코드와 데이터를 포함하고 있다.

 

2. 이후 클래스 파일을 로딩하고 링크하는 과정을 거침. 이 과정에서 클래스 파일을 메모리에 로딩하고 필요한 라이브러리를 로딩

  • 로딩
    • 프로그램에서 "로딩"은 파일이나 데이터를 메모리에 올리는 과정을 의미한다. 자바에서는 클래스 파일이 로딩되는 과정을 말한다. 이 과정에서 클래스 파일의 바이트 코드가 메모리에 로드되고, 해당 클래스의 정보가 메모리에 등록된다. 로딩은 프로그램 실행 전에 발생하며, 클래스가 필요할 때마다 로딩된다.
  • 링크
    • 프로그램에서 "링크"는 여러 모듈(코드 조각)을 하나의 실행 파일로 결합하는 과정을 의미한다. 이 과정은 컴파일러나 링커(Linker)가 수행하며, 주로 컴파일 이후에 발생한다. 자바에서는 클래스 로딩 후 링크 단계를 거친다. 이 과정에서는 메모리에 로드된 클래스들이 연결되어 하나의 실행 가능한 코드로 만들어진다. 링크 단계에서는 다음과 같은 작업들이 수행된다.
    • 검증(Verification): 로딩된 클래스 파일이 유효한지 검사. 예를 들어, 클래스 파일이 올바른 형식인지, 상위 클래스나 인터페이스가 존재하는지 등을 검사한다.
    • 준비(Preparation): 클래스 변수(static 변수)에 대한 메모리 공간을 할당하고, 기본값으로 초기화한다.
    • 해결(Resolution): 클래스나 인터페이스에 대한 참조를 실제 메모리 주소로 변환한다. 즉, 다른 클래스나 인터페이스를 참조하는 클래스를 로드하고, 참조되는 클래스나 인터페이스를 검색하는 작업을 수행한다.
    • 링크 단계가 완료되면, JVM은 바이트 코드를 실행할 수 있는 형태로 준비되며, 이후에 바이트 코드를 해석하고 실행한다.

 

3. 이후 JVM은 자바 바이트 코드를 해석하고, 실행. 이 과정에서 JIT(Just-In-Time) 컴파일러를 사용하여 바이트 코드를 네이티브 코드로 변환하고 이를 실행.

  • JIT(Just-In-Time)컴파일러
    • JIT(Just-In-Time) 컴파일러는 JVM이 실행하는 바이트 코드를 실시간으로 기계어로 번역하는 컴파일러다. JIT 컴파일러는 프로그램이 실행 중일 때, JVM이 코드를 해석해서 실행하는 것보다 빠르게 실행되도록 최적화된 기계어 코드를 생성한다.
    • JIT 컴파일러는 프로그램의 실행 패턴을 분석하여 최적화된 코드를 생성한다. 일반적으로 JVM은 프로그램을 해석해서 실행하기 때문에, 같은 코드를 반복해서 실행할 경우에도 매번 해석 작업이 수행되어 성능 저하가 발생한다. 하지만 JIT 컴파일러는 이러한 반복 작업을 미리 예측하고, 이에 대한 최적화된 기계어 코드를 생성한다.
    • JIT 컴파일러의 두가지 종류
      첫째는 메서드 단위의 JIT 컴파일러이며, 이는 메서드가 처음 호출될 때 메서드 본문 전체를 컴파일한다. 이후에는 컴파일된 코드를 실행한다.
      둘째는 인라인 JIT 컴파일러이며, 이는 메서드 호출 시점에 호출되는 메서드의 일부 코드를 호출한 메서드 내부에 삽입하는 방식으로 최적화한다. 이를 인라이닝(Inlining)이라고 한다.
    • JIT 컴파일러는 JVM의 성능을 향상시키는데 중요한 역할을 한다. JIT 컴파일러는 코드의 실행 패턴을 분석하고, 이를 바탕으로 최적화된 코드를 생성하기 때문에, 일반적으로 프로그램의 실행 속도를 빠르게 만들어준다.

 

4. JVM은 가비지 컬렉션을 사용하여 메모리를 관리 함. 가비지 컬렉션은 더 이상 사용되지 않는 객체를 자동으로 삭제하여 메모리를 해제.

  • 가비지 컬렉션(Garbage Collection)
    • 가비지 컬렉션(Garbage Collection)은 자바의 중요한 특징 중 하나다. 가비지 컬렉션은 JVM에서 자동으로 메모리를 관리하는 기능으로, 더 이상 사용하지 않는 객체를 메모리에서 제거하는 역할을 한다.
      자바에서는 개발자가 메모리 할당과 해제를 수동으로 처리하지 않아도 되기 때문에, 메모리 누수(Memory Leak)나 다른 메모리 관련 버그를 줄일 수 있다.
    • 가비지 컬렉션 동작 단계
      Mark: 가비지 컬렉션은 루트(root) 객체를 찾고, 루트 객체에서 참조하는 모든 객체를 찾아서 마킹
      Sweep: 마킹되지 않은 객체들은 사용되지 않은 객체로 판단하고, 이를 제거
      Compact: 제거된 객체들의 메모리 공간을 정리하여 메모리 단편화를 방지함
    • 가비지 컬렉션은 자바에서 메모리 관리를 단순화하고, 개발자가 메모리 관리를 신경쓰지 않아도 되도록 만들어준다. 하지만 가비지 컬렉션이 메모리를 수거하는 동안 일시적으로 프로그램이 멈추는 현상이 발생할 수 있다. 이를 가비지 컬렉션 지연(Garbage Collection Pause)이라고 한다.
      가비지 컬렉션은 메모리 관리를 단순하고 안정적으로 만들어준다. 하지만 메모리 수집 과정에서 발생하는 지연 현상으로 인해, 빠른 응답성이 요구되는 프로그램에서는 가비지 컬렉션의 영향을 고려해야 한다.

 

5. 마지막으로, 프로그램 실행이 완료되면 JVM은 자원을 해제하고 종료

  • 자원 해제
    • 프로그램이 실행되는 동안, 프로그램에서 사용한 자원(메모리, 파일 등)을 해제하는 것을 자원 해제(Resource Release)라고 한다.
      자원을 해제하는 것은 프로그램의 안정성과 성능을 유지하기 위해서 중요한 작업 중 하나다. 예를 들어, 프로그램이 파일을 열어서 사용한 후에 이를 닫지 않고 종료되면, 이 파일은 계속해서 열린 상태로 남아있게 된다. 이러한 상황에서는 해당 파일이 다른 프로그램에서 사용될 수 없고, 시스템 자원을 불필요하게 차지하게 된다. 따라서, 프로그램에서 사용한 자원은 사용이 끝난 후에는 반드시 해제되어야 한다.
      자원 해제는 다음과 같은 작업을 수행한다.
      1. 메모리에서 할당한 자원의 반환
      2. 열린 파일, 소켓, 데이터베이스 연결 등의 해제
      3. 프로세스나 쓰레드 등의 종료
    • 메모리에서 할당한 자원의 반환열린 파일, 소켓, 데이터베이스 연결 등의 해제프로세스나 쓰레드 등의 종료자원을 해제하지 않으면, 시스템 자원이 낭비되거나, 예기치 않은 동작이 발생할 수 있다. 따라서, 프로그램에서 자원을 사용한 후에는 항상 해당 자원을 해제해야 한다.
반응형

'Back-End > Java' 카테고리의 다른 글

Java(2)  (0) 2023.03.14
Java 예습  (0) 2023.03.11
Java 예습  (0) 2023.03.05

댓글