본문 바로가기
public void static main/Book

[JVM 밑바닥] 7장 클래스 로딩 메커니즘

by 햄리뮤 2024. 11. 17.
반응형

공부시작!

책표지

1. 클래스 로딩 시점

JVM은 클래스를 "필요한 순간"에 로딩합니다. 정확한 시점은 아래와 같습니다:

  • 클래스를 사용할 때: 예를 들어, new 키워드로 객체를 생성하거나, 클래스의 정적 메서드/변수를 호출할 때.
  • Class.forName() 호출 시: 리플렉션을 통해 클래스를 로드할 때.
  • JVM의 기본 실행: JVM이 시작되면서 메인 클래스를 로드합니다.

2. 클래스 로딩 처리 과정 (3단계)

클래스 로딩은 크게 로딩 → 링크 → 초기화의 3단계로 나뉩니다.

(1) 로딩 (Loading)

  • 클래스 파일(.class)을 찾고 읽어들여 메모리에 로드합니다.
  • 이 작업은 JVM 내의 클래스 로더(ClassLoader)가 담당합니다.
  • 메서드 영역에 클래스 정보를 저장 합니다.
  • 클래스 객체(java.lang.Class)를 생성 합니다.

(2) 링크 (Linking)

  1. 검증(Verification): 바이트코드 검증
    • 클래스 파일이 유효한지 검증합니다.
    • JVM 스펙에 맞지 않으면 VerifyError 발생.
  2. 준비(Preparation): static 변수 메모리 할당, 기본값으로 초기화
    • 클래스의 정적 변수(static fields)를 메모리에 할당하고 기본값(0, null 등)으로 초기화.
  3. 해결(Resolution): 심볼릭 레퍼런스를 실제 레퍼런스로 교체
    • 클래스 내부에서 참조하는 다른 클래스(예: 상속받는 클래스, 메서드 호출 등)를 확인하고 연결.

(3) 초기화 (Initialization)

  • 클래스의 정적 변수에 명시된 값으로 초기화하고, 정적 초기화 블록(static {})을 실행합니다.

3. 클래스 로더 (Class Loader)

JVM에는 여러 클래스 로더가 계층적으로 동작합니다.
주요 클래스 로더와 역할은 아래와 같습니다:

  1. Bootstrap ClassLoader
    • 가장 기본적인 클래스 로더로, JDK 내부의 핵심 클래스(java.lang, java.util 등)를 로드.
    • C++로 구현되어 있음.
  2. Extension ClassLoader
    • JAVA_HOME/lib/ext 폴더에 있는 확장 클래스들을 로드.
  3. Application ClassLoader
    • 애플리케이션 코드(classpath 경로의 클래스)를 로드.
    • 사용자가 작성한 클래스와 외부 라이브러리(JAR 파일)도 여기에 포함됨.
  4. Custom ClassLoader
    • 사용자가 직접 정의하여 동작을 변경할 수 있는 클래스 로더.
    • 주로 애플리케이션에서 특정 파일 구조나 동적 로딩이 필요할 때 사용.

4. 자바 모듈 시스템 (Java 9 이상)

자바 모듈 시스템은 JAR 파일의 단점을 보완하기 위해 등장했습니다.
주요 목적은 모듈화, 캡슐화, 의존성 관리입니다.

주요 특징

  • 모듈 정의
    • 각 모듈은 module-info.java 파일로 정의됩니다.
    • 예:
module com.example.myapp { 
	requires java.sql; // 의존 모듈 
	exports com.example.myapp.services; // 외부에 공개할 패키지 
}
  • 의존성 관리
    • 컴파일 시점에 필요한 모듈과 런타임에 필요한 모듈을 명시적으로 선언 가능.
    • 불필요한 모듈 접근 차단.
  • 강한 캡슐화
    • 모듈 외부에서 특정 패키지에 접근하지 못하도록 제한.
  • JVM의 작은 런타임 지원
    • 필요한 모듈만 포함하는 맞춤형 런타임 이미지 생성 가능 (jlink 사용).

장점

  • 애플리케이션 크기 감소.
  • 코드 가독성 향상.
  • 유지보수성 개선.
  • 강력한 캡슐화: 모듈 내부 구현 숨김
  • 명시적 의존성: requires로 필요한 모듈 선언
  • 서비스 지향: provides/uses로 서비스 구현
  • 플랫폼 모듈화: JDK 자체가 모듈화됨

단점

  • 초기 도입 시 복잡성 증가.
  • 기존의 JAR 중심 프로젝트와 호환성을 맞추는 데 추가 작업 필요.

추가로 정리한 부분입니다.

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

  • JVM은 바이트코드(.class 파일)를 런타임에 기계어로 번역해서 실행합니다.
  • 이 번역 작업을 효율적으로 하기 위해 JIT 컴파일러가 동작합니다.
  • 자주 실행되는 코드(핫스팟)는 JIT이 최적화해 더 빠르게 실행되도록 만들어줍니다.

왜 중요한가?

  • JVM 성능을 높이는 핵심 요소입니다.
  • 최적화 전략 때문에 코드 실행 속도가 예상보다 빠르거나 느릴 수 있음.

Class.forName()과 ClassLoader 차이

둘 다 클래스를 로드하지만, 차이점이 있어요.

  • Class.forName("클래스명"): 클래스를 로드 + 초기화까지 진행.
  • ClassLoader.loadClass("클래스명"): 클래스를 로드만 진행(초기화는 나중에).

언제 사용할까?

  • 리플렉션이나 동적 로딩을 사용할 때 ClassLoader로 필요한 시점에만 로딩 가능.

컴파일과 인터프리트

  • 자바는 컴파일 언어이자 인터프리트 언어입니다.
  • 컴파일: 자바 코드를 바이트코드(.class)로 변환.
  • 인터프리트: JVM이 바이트코드를 기계어로 번역하며 실행.

HotSpot JVM의 튜닝

  • JVM은 실행 시 여러 옵션으로 튜닝 가능합니다.
    • -Xmx: 힙 메모리의 최대 크기 설정.
    • -XX:+UseG1GC: GC 알고리즘 변경(G1 GC 사용).
    • -XX:+PrintGCDetails: GC 로그 출력.
  • 대규모 프로젝트에서 성능을 최적화할 때 매우 중요합니다.
반응형

댓글