hyeonga_code

JVM_06_JVM 구성 요소_런타임 데이터 영역_스택 영역 본문

JVM

JVM_06_JVM 구성 요소_런타임 데이터 영역_스택 영역

hyeonga 2024. 5. 8. 10:59
반응형

JVM 구성 요소

- Class Loader
    - Bootstrap Class Loader
    - Extension Class Loader
    - System/Application Class Loader
- Execution Engine
- Runtime Data Area

 

런타임 데이터 영역 Runtime Data Area

 

프로그램의 실행 도중 사용되는 다양한 데이터를 저장하는 영역입니다.
클래스 로딩 과정이 완료되면 로드된 클래스에 대한 정보를 저장합니다.

주요 런타임 데이터 영역
  - 메소드 영역
  - 힙 영역
  - 스택 영역
  - PC 레지스터
  - 네이티브 메소드 스택

스택 영역 Stack Area

자바 스레드가 실행될 때 메소드 호출과 실행을 관리합니다.
각 스레드는 자신의 스택 영역이 스레드 생성시에 할당됩니다.
메소드의 호출과 반환 데이터를 저장하는 데 사용됩니다.

LIFO Last In First Out 으로 메소드 호출 시 각 메소드의 스택프레임이 push 됩니다.
스택 프레임에는 로컬변수, 입력 매개변수, 반환값, 메소드 호출 정보가 포함됩니다.
메소드가 종료되면 pop 으로 스택프레임이 스택에서 제거됩니다.
스택을 공유하지 않아 데이터의 격리가 보장되며 안전성이 보장됩니다.

객체 참조 변수가 Stack에 저장되는 이유

자바의 메모리 관리 방식과 실행 모델 때문입니다.

1) 스코프 및 생명 주기 관리
참조 변수는 특정 메소드 내에서 선언되며 로컬변수로 취급됩니다.
메소드 호출 시 메소드의 로컬변수스택에 저장됩니다.
각 메소드에 대해 스택프레임이 생성되고 로컬변수와 매개변수가 저장됩니다.
메소드 종료 시 해당 스택 프레임은 내용과 함께 제거되어 참조 변수의 생명주기는 메소드의 생명주기와 같다고 할 수 있습니다.

2) 메모리의 효율성
LIFO의 특징으로 미리 정의된 크기를 가지고 있습니다.

3) 성능 최적화
CPU와의 근접성으로 접근 속도가 빨라 성능이 향상될 수 있습니다.

4) 스레드 안전성
스택에 저장된 참조 변수는 해당 스레드에서만 접근할 수 있으므로 스레드 간의 데이터 충돌을 방지합니다.

객체 참조 변수가 Stack에 저장되는 과정

1) 메소드 호출
JVM은 각 메소드 호출에 대해 스택 프레임을 생성합니다.
해당 메소드의 실행에 대한 모든 정보를 포함합니다.
지역 변수, 매개변수, 반환값, 메소드 호출과 관련된 추가 정보 등이 포함됩니다.

2) 스택 프레임 구성
스택프레임 내부에서 지역 변수 섹션에 객체 참조 변수가 저장됩니다.
지역 변수 섹션은 메소드의 실행동안 사용될 모든 지경 변수의 슬롯을 포함합니다.

3) 객체 생성과 참조 할당
new 키워드가 실행되면 힙 메모리에 객체를 위한 공간을 할당합니다.
객체의 생성자를 호출하여 객체를 초기화합니다.
객체를 생성한 후 JVM은 생성된 객체의 메모리 주소를 반환합니다.
이 참조는 호출된 메소드의 지역 변수 섹션에 저장된 참조 변수에 할당됩니다.

public class Example {
    public void exampleMethod() {
        MyClass object = new MyClass(); 
        // 'object' 참조 변수가 스택에 저장됩니다.
    }
}

 

4) 메소드 실행
해당 참조 변수는 객체에 접근하는데 사용됩니다.
참조 변수를 통해 객체의 메소드를 호출하거나 필드에 접근할 수 있습니다.

5) 메소드 종료와 스택 프레임 제거
메소드 실행이 완료되면 해당 메소드의 스택 프레임은 스택에서 제거됩니다.
지역 변수 섹션에 저장된 모든 참조 변수도 함께 제거됩니다.
해당 참조 변수를 더 이상 유효하지 않습니다.
참조하고 있던 객체는 다른 참조가 없는 경우 GC에 의해 메모리에서 회수될 수 있습니다.


AI 답변
객체 참조 변수가 스택에 저장되는 과정은 다음과 같습니다.
1) 객체의 생성
먼저, 객체가 힙 메모리에 생성됩니다. 이때 실제 객체의 데이터와 메서드가 저장되며, 힙 메모리의 주소를 가리키는 참조 변수가 생성됩니다.
2) 참조 변수의 할당
메서드 내에서 객체를 참조할 변수를 선언하면 해당 참조 변수는 스택 메모리에 생성됩니다. 이때 참조 변수는 힙 메모리에 저장된 객체의 주소를 가리키고 있습니다.
3) 참조 변수 값의 변경
참조 변수에 다른 객체를 할당하면 해당 참조 변수는 새로운 객체의 주소를 가리키게 됩니다. 이때 스택 메모리에 저장된 참조 변수의 값만 변경되고, 힙 메모리에 있는 객체는 그대로 남아 있습니다.
4) 참조 변수 범위를 벗어날 때
메서드가 종료되거나 참조 변수가 더 이상 필요하지 않을 때 스택 메모리에 있는 참조 변수는 스택 프레임과 함께 사라지게 됩니다. 이때 힙 메모리에 있는 객체는 가비지 컬렉터에 의해 회수될 수 있습니다.

 

메모리 누수 Memory Leak

필요하지 않은 메모리를 적절히 해제하지 않고 계속 점유하는 상태입니다.
컬렉션에서 객체를 제거하지 않고 참조만 유지하는 상태입니다.

  • 불필요한 객체 참조를 유지하는 경우
  • 리스너와 콜백
  • 정적 필드를 사용
  • 애플리케이션 실행동안 계속 유지
  • 외부 리소스와의 연결
  • 데이터페이스 커넥션, 파일 핸들, 네트워크 소켓 등 외부 리소스와의 연결을 제대로 종료하지 않은 경우

예방 방법

  • 객체 참조를 명확하게 합니다.
  • 사용이 끝난 객체는 null로 처리하거나 컬렉션에서 제거합니다.
  • 리소스 해제를 관리합니다.
  • finally 블록이나 try-with-resources를 사용합니다.
  • 리스너와 콜백을 관리합니다.
  • 프로파일링 도구를 사용합니다.
  • VisualVM Eclipse Memory Analyzer

프로파일링 도구의 기본 동작 방식

1) 데이터 수집 : 힙 메모리 사용량, 객체 생명주기, 스레드의 활동 상태
2) 메모리 덤프 : 특정 시점에서의 JVM의 힙 메모리 상태를 파일로 저장한 것으로 모든 객체와 클래스, 각 객체의 메모리 사용량 및 객체 간 참조 정보를 포함합니다.
3) 분석 : 메모리 누수, 스레드 병목 현상, CPU 과다 사용 등의 문제를 식별합니다. 분석 결과를 토대로 적절한 최적화를 수행할 수 있습니다.

VisualVM
JDK에 포함된 도구입니다.
1> 실시간 모니터링 : CPU, GC 활동, 힙 메모리 사용량, 스레드 상태 등을 실시간으로 모니터링합니다.
2> 스레드 덤프 : 스레드의 현재 상태를 분석하여 병목현상이나 교착 상태를 식별할 수 있습니다.
3> 힙 덤프 분석 : 힙 덤프를 생성하고 분석하여 가장 많은 메모리를 사용하는 객체와 클래스를 식별하고, 메모리 누수를 찾아낼 수 있습니다.

Eclipse Memory Analyzer_MAT
1> 덤프 파일 분석 : 메모리 덤프 파일을 분석하여 메모리 사용 패턴, 메모리 누수, 객체 크기 및 참조 체인을 제공합니다.
2> 레포트 생성 :
누수 의심 지점을 식별하고 해당 객체에 대한 자세한 참조 경로와 누수 원인은 보고서 형태로 제공합니다.
3> 객체 쿼리 : OQL을 사용하여 덤프 내의 객체를 질의하고 특정 조건에 맞는 객체 집합을 검색할 수 있습니다.

  • 코드 리뷰 및 테스팅
  • 단위 테스트, 통합 테스트
반응형