읽기 전

  • 불필요한 코드나 잘못 작성된 내용에 대한 지적은 언제나 환영합니다.
  • 개인적으로 사용해보면서 배운 점을 정리한 글입니다.

문제 제기

Java는 JVM이라는 가상 머신을 통해 OS 종류와는 관계 없이 구동 환경만 적합하면 코드를 실행할 수 있다. 따라서 Java의 특징적인 컴파일 환경, JVM의 구조 등을 정리하려 한다.

해당 파트는 java 소스코드 작성 후 컴파일 프로세스와 jvm에 바이트 코드 실행 시 내부 데이터를 저장 및 관리하는 흐름에 대한 내용이다.

컴파일 흐름 및 자바 가상 머신의 구성

Development_Java_compile_runtime_environment_001.png

  1. 개발자가 자바 소스 코드(.java)를 작성
  2. 자바 컴파일러(javac)가 자바 소스 코드파일 컴파일 수행
    • 자바 바이트코드(.class) 파일 생성
    • OS는 non-Readable, JVM은 Readable
    • 바이트 코드의 명령어는 1바이트 크기의 opcode와 추가 피연산자로 구성
  3. 컴파일된 바이트 코드를 JVM의 클래스 로더에 전달
  4. 클래스 로더가 클래스 파일을 JVM 내부로 로딩, 파일을 분석하여 런테임 데이터 영역에 배치
    • 동적 로딩을 수행하므로 런타임 시점이 되어야 모든 코드가 JVM과 링크됨
    • 클래스 로더 세부 동작
      • 로드 : 바이트 코드 파일을 가져와서 JVM 메모리에 적재
      • 검증 : 자바 언어 및 JVM 명세에 명시된 대로 구성되어 있는지 검사
      • 준비 : 클래스가 필요로 하는 메모리 할당 (필드, 메소드, 인터페이스 등)
      • 분석 : 클래스의 Constatnt Pool 내에 저장된 모든 Symbolic Reference를 Direct Reference로 변경
      • 초기화 : 클래스 변수를 적절한 값으로 초기화(static)
  5. 실행 엔진(Execution Engine)은 JVM 메모리에 적재된 바이트 코드들을 명령어 단위로 하나씩 가져와서 실행함, 실행 방식은 두 가지로 나뉨
    • 인터프리터 : 바이트 코드 명령어를 하나씩 읽고 해석하고 실행, 명령어 실행 단위 시간은 빠르나 전체적인 실행 속도는 느림
    • JIT(Just-In-Time) 컴파일러 : 인터프리터의 단점을 보완하기 위해 도입되었으며 바이트 코드 전체를 컴파일하여 기계어로 변경한 후 해당 메소드를 더 이상 인터프리팅하지 않고 바이너리 코드로 직접 실행, 전체 실행 속도는 빠르나 초기 변환 비용이 발생
  • 가비지 컬렉터(Grabage Collector)
    1. 참조되지 않는 객체들을 탐색 후 삭제
    2. 삭제된 객체의 메모리 반환
    3. 힙 메모리 공간 확보(다른 공간의 경우도 확보할 경우 있긴 함)

+ Recent posts