about JVM

2025. 9. 30. 22:27·JAVA

1. JVM의 역할과 Java 바이트코드

JVM은 컴파일된 Java 코드를 실행하는 가상 머신입니다. Java 컴파일러(javac)는 .java 소스 코드를 특정 하드웨어나 운영체제에 종속되지 않는 중간 언어인 Java 바이트코드(Bytecode)로 변환하여 .class 파일에 저장합니다. 이 .class 파일은 JVM이 설치된 모든 환경에서 동일하게 실행될 수 있습니다.

JVM의 주요 특징은 다음과 같습니다.

  • 스택 기반 가상 머신: 레지스터 기반으로 동작하는 대부분의 하드웨어 아키텍처와 달리, JVM은 스택을 사용하여 연산을 수행합니다.
  • 심볼릭 레퍼런스: 메모리 주소를 직접 참조하는 대신, 런타임 상수 풀을 통한 심볼릭 참조를 사용하여 객체 및 메서드에 접근합니다. 이는 동적 로딩 및 링크를 용이하게 합니다.
  • 가비지 컬렉션 (Garbage Collection): JVM은 힙(Heap) 영역에 생성된 객체 중 더 이상 참조되지 않는 객체를 자동으로 회수하여 메모리를 관리합니다. 이를 통해 개발자는 메모리 해제에 대한 부담을 줄일 수 있습니다.
  • 플랫폼 독립성 보장: int와 같은 기본 자료형의 크기를 명확히 정의하고, 플랫폼 간 바이트 순서 차이를 해결하기 위해 네트워크 바이트 오더(빅 엔디안)를 사용하여 플랫폼 독립성을 확보합니다.

 

2. JVM 아키텍처

JVM은 크게 클래스 로더(Class Loader), 런타임 데이터 영역(Runtime Data Areas), 실행 엔진(Execution Engine)의 세 가지 주요 구성 요소로 나뉩니다.

2.1. 클래스 로더 (Class Loader)

클래스 로더는 컴파일된 .class 파일을 런타임 데이터 영역에 동적으로 로드하는 역할을 담당합니다. 로딩은 애플리케이션 시작 시점이 아닌, 특정 클래스가 처음으로 참조되는 시점에 발생합니다.

  • 계층 구조 및 위임 모델: 클래스 로더는 부모-자식 관계의 계층 구조를 가집니다. 클래스 로드 요청이 들어오면, 현재 로더는 직접 처리하지 않고 상위 로더에게 먼저 요청을 위임합니다. 최상위인 부트스트랩 클래스 로더까지 요청이 도달해도 클래스를 찾지 못하면, 그제야 요청을 받았던 하위 로더가 직접 클래스를 찾아 로드합니다. 이 모델은 클래스의 중복 로드를 방지하고 보안을 강화합니다.
  • 종류:
    • 부트스트랩 클래스 로더: JAVA_HOME/lib에 있는 핵심 Java API를 로드합니다. 네이티브 코드로 구현됩니다.
    • 익스텐션 클래스 로더: JAVA_HOME/lib/ext의 확장 라이브러리를 로드합니다.
    • 시스템 클래스 로더: 사용자가 지정한 -classpath 또는 $CLASSPATH에 있는 애플리케이션 클래스를 로드합니다.

2.2. 런타임 데이터 영역 (Runtime Data Areas)

JVM이 프로그램을 실행하는 동안 사용하는 메모리 공간으로, 스레드 간 공유 여부에 따라 구분됩니다.

  • 모든 스레드 공유 영역:
    • 힙 (Heap): new 키워드로 생성된 모든 객체 인스턴스와 배열이 저장되는 공간입니다. 가비지 컬렉션의 주된 대상입니다.
    • 메서드 영역 (Method Area): 클래스의 메타데이터(클래스 구조, 필드, 메서드 데이터), static 변수, 런타임 상수 풀 등이 저장됩니다. Java 8 이전에는 PermGen(Permanent Generation)이라 불렸으며, 이후 Metaspace로 대체되었습니다.
  • 스레드별 개별 영역:
    • JVM 스택 (JVM Stack): 메서드 호출 시마다 스택 프레임(Stack Frame)이 생성되어 저장(push)되고, 메서드가 종료되면 제거(pop)됩니다. 각 스택 프레임은 지역 변수 배열, 피연산자 스택, 런타임 상수 풀에 대한 참조를 포함합니다. StackOverflowError가 발생하는 영역입니다.
    • PC 레지스터 (PC Register): 각 스레드는 현재 실행 중인 JVM 명령어의 주소를 저장하는 PC 레지스터를 가집니다. 이를 통해 스레드 간 컨텍스트 스위칭 이후에도 실행할 위치를 기억할 수 있습니다.
    • 네이티브 메서드 스택 (Native Method Stack): JNI(Java Native Interface)를 통해 호출되는 네이티브 코드(C/C++)의 실행을 위한 스택입니다.

2.3. 실행 엔진 (Execution Engine)

실행 엔진은 런타임 데이터 영역에 로드된 바이트코드를 실제로 실행하는 역할을 합니다.

  • 인터프리터 (Interpreter): 바이트코드를 한 줄씩 읽고 해석하여 실행합니다. 초기 구동은 빠르지만, 반복적인 코드 실행 시 비효율적입니다.
  • JIT (Just-In-Time) 컴파일러: 인터프리터의 단점을 보완하기 위해 도입되었습니다. 프로그램 실행 중(런타임)에 프로파일러(Profiler)가 자주 사용되는 코드, 즉 핫스팟(Hot Spot)을 식별합니다. JIT 컴파일러는 이 핫스팟을 해당 플랫폼에 최적화된 네이티브 코드(기계어)로 컴파일하여 캐시에 저장합니다. 이후 해당 코드가 호출될 때는 인터프리팅 없이 캐시된 네이티브 코드를 직접 실행하여 성능을 극적으로 향상시킵니다. 이 과정 때문에 Java 애플리케이션은 실행 초기에 '웜업(Warm-up)' 시간을 거치며 점차 성능이 최적화됩니다.

 

3. 바이트코드와 런타임 오류 분석: NoSuchMethodError 사례

JVM의 동작을 이해하는 것은 실제 오류를 분석할 때 매우 중요합니다. 라이브러리 업데이트 후 애플리케이션을 재컴파일하지 않았을 때 발생하는 NoSuchMethodError는 대표적인 사례입니다.

  • 현상: void를 반환하던 메서드가 User 객체를 반환하도록 라이브러리가 변경되었습니다. 기존 라이브러리로 컴파일된 애플리케이션은 이 새로운 라이브러리를 사용하면 NoSuchMethodError를 발생시킵니다.
  • 원인: JVM은 메서드를 식별할 때 이름과 파라미터뿐만 아니라 반환 타입까지 포함하는 메서드 시그니처를 사용합니다. 에러 메시지 ...addUser(Ljava/lang/String;)V에서 마지막 V는 void 반환 타입을 의미합니다. 기존 코드는 반환 타입이 V인 메서드를 찾지만, 새 라이브러리에는 해당 시그니처의 메서드가 존재하지 않으므로 오류가 발생합니다. 새 라이브러리의 메서드 시그니처는 ...addUser(Ljava/lang/String;)Lcom/nhn/user/User;가 되기 때문입니다.
  • 교훈: 이 사례는 소스 코드 수준의 호환성과 바이트코드 수준의 호환성이 다를 수 있음을 보여줍니다. 개발자는 메서드 시그니처가 바이트코드 수준에서 어떻게 표현되는지 이해함으로써 복잡한 런타임 의존성 문제를 해결할 수 있습니다.

 

4. 결론

JVM은 Java의 플랫폼 독립성과 고성능을 가능하게 하는 정교한 시스템입니다. 클래스 로더를 통한 동적 로딩, 체계적으로 분리된 런타임 데이터 영역, 그리고 인터프리터와 JIT 컴파일러가 조화롭게 동작하는 실행 엔진은 JVM의 핵심입니다. JVM의 내부 동작 원리에 대한 이해는 단순한 코드 작성을 넘어, 애플리케이션의 성능을 극한으로 끌어올리고 예측 불가능한 런타임 오류에 효과적으로 대응할 수 있는 고급 개발자로 성장하기 위한 필수적인 지식입니다.

참고 자료

  • 네이버 D2 - JVM Internal

'JAVA' 카테고리의 다른 글

Serializable  (0) 2025.12.04
JDK, JRE, JVM  (0) 2025.09.30
Primitive Type과 Reference Type  (0) 2025.09.30
자바의 hashCode(), hash()에 대하여  (0) 2025.03.10
'JAVA' 카테고리의 다른 글
  • Serializable
  • JDK, JRE, JVM
  • Primitive Type과 Reference Type
  • 자바의 hashCode(), hash()에 대하여
이경빈
이경빈
이 블로그의 게시글을 바탕으로 학습하는 것을 권장하지 않습니다. 이 블로그의 게시글을 통해 무엇을 학습할 수 있고 무엇을 학습해야 하는지 알 수 있는 이정표 및 목차가 되었으면 합니다.
  • 이경빈
    메모용 블로그
    이경빈
    • 분류 전체보기 (44)
      • 기본개념 (0)
      • Git (2)
      • OOP (객체 지향 프로그래밍) (1)
      • CS (2)
      • JAVA (7)
        • 문법 (0)
        • stream api (1)
        • 자료구조 (1)
      • Spring (11)
        • Spring Context (1)
        • Spring beans (1)
        • Spring MVC (0)
        • RestTemplate (1)
        • JPA (1)
        • Mockito (1)
        • Spring Security (4)
        • Async (1)
      • Gradle (0)
      • 컴퓨터 네트워크 (6)
      • DBMS (2)
        • SQL (2)
      • 자료구조 (1)
      • 위클리페이퍼 (5)
      • AWS (0)
      • 프로젝트 (3)
        • 트러블슈팅 (1)
        • 회고 (2)
        • git hub 프로젝트 (0)
        • git in java (0)
      • 운영체제 (1)
      • Project (0)
        • 고민거리들 (0)
        • ai에게 요구한 수정사항 (0)
  • 전체
    오늘
    어제
  • hELLO· Designed By정상우.v4.10.3
이경빈
about JVM
상단으로

티스토리툴바