코드 그라데이션
JVM 기본 구조(2) 본문
JVM 기본 구조
클래스 로더
- .java 파일을 컴파일해서 얻는 .class class을 메모리 로드
- 로드할 클래스가 여럿이면 Main() 메서드를 포함하는 클래스를 우선 로드
- 로드, 링크, 초기화 단계를 거침
(JVM 내장) 클래스 로더
1.부트스트랩 클래스 로더
• java.lang, java.net, java.util, java.io 같은 표준 Java 패키지 로드
• rt.jar 파일에 들어있는 핵심 라이브러리
2. 확장 클래스 로더
• $JAVA_HOME/ jre / ext
• 확장 라이브러리 클래스 로드
3. (응용 프로그램) 클래스 로더
• (classpath , cp) 클래스 경로에 있는 클래스 로드
• 일반적으로 개발자가 작성한 코드를 포함하는 클래스
• 로더가 클래스 이름을 찾지 못할 경우
NoClassDefFoundError, ClassNotFoundExecptionClassNotFoundExecption 에러 발생
클래스 링크
• 클래스 로드 후 링크 절차를 수행하며 클래스간 의존관계를 분석하고 함께 링크
• 확인 : .class 파일자체에 대한 구조 정합성 검증 실패 시 VerifyExceptionVerifyException에러 발생
• 준비 : 정적 필드에 메모리를 할당하고 기본 값으로 초기화. 생성자 호출 전이며 일단 0 초기화
JVM 클래스 초기화
• 클래스 생성자 호출
• 정적 필드에 00이 아닌 초깃값을 기술할 경우 실제 값으로 초기화
• 멀티스레드 환경을 고려하지 않을 경우 클래스 초기화 중 오류발생 가능
JVM Execution engine
• Interpreter
• 바이트 코드 명령을 실행
• 메소드가 여러 번 호출되면 매번 번역
• JIT compiler
• Garbage collector
JIT(Just In Time) compiler
• Java bytecode byte code를 실제 기계어로 번역
• JVM이 반복되는 코드를 발견할 경우 효율을 높일 목적으로 사용
• Intermediate code generator
• Code optimizer
• Target code generator
• Profiler (Hotspot)
• 실행 기록을 모아 자주 사용되는 코드에 주로 적용 반복문
• 프로그램을 오래 실행 할 수록 성능개선에 유리
JVM Runtime data area
Method area
• 상수 풀
• 필드
• 메서드 코드 등이 저장되는 영역
Heap area
• 클래스 인스턴스들이 저장되는 런타임 데이터 영역으로 GC가 관리
• new 연산으로 생성된 모든 클래스 인스턴스가 저장되는 영역
• 멀티스레드 환경에서 Heap 영역은 모든 스레드가 공유 동기화 필수
Stack area
• 각스레드마다 별도의 스택을 가짐
• 메서드 호출 시 스택 프레임이 증가하며 각 반환 시 프레임 자동 소멸
• 지역변수, 피연산자, 스택 프레임 데이터 등 세 가지 요소로 구성
Stack area - 지역변수
• 지역변수들을 배열 형식으로 저장관리
• 바이트 코드 수준에서 각 지역변수에 대한 접근은 배열의 인덱스로 대체
• 배열의 최대 크기는 컴파일 타임에 결정 (C/C++) 와 비슷
Stack area - 피연산자와 프레임
• 스택기반 머신 형태로 작동하도록 구성
• 연산의 중간결과도 스택에 저장
• 스택의 최대 크기는 컴파일 타임에 결정
• 메서드에 대한 모든 심볼정보 및 예외처리 관련 catch 블록 정보 등은 프레임 데이터 영역 사용
PC(Program Counter) register
• 일반 CPU( EIP register) 처럼 Program CounterCounter를 가지며 같은 역할 수행
• 스레드 마다 별도 문맥을 가질 수 있도록 개별 PC register register를 가짐
Native method 스택
• C/C++ 같은 Native 언어로 개발된 메서드를 지원하기 위한 스택
• 스레드 마다 별도로 제공
• JNI (Java Native Interface)
JVM heap 영역
• Metaspace (Java 8)
• 로드되는 클래스, 메소드 등에 관한 메타 정보 저장 자동확장 가능
• Java heap이 아닌 Native 메모리 영역 사용
• 리플렉션 클래스 로드 시 사용 (Spring)
우리가 request 가 오면 그 코드들을 클래스에 넣어서 구현하는데 이 때 자동으로 class를 생성도 해야 할 것이고 나중엔 GC를 구동을 시키기도 해야 한다.
이 과정에서 쓰이는 것이 Reflection 이다.
이 때 생각해 봐야 할 것.
만약 서비스 개발을 했는데 어떤 특수한 이유 때문에 heap 영역이 Metaspace 영역보다 더 커져야 할 수도 있다.
이걸 계산하는 기준이 request 인데, 보통 "단위 시간" 이다.
단위시간동안 리퀘스트가 얼마나 오냐, 그로 인해 TPS(Transaction per sec)가 얼마나 발생하느냐.
이런 계산 하에 메모리를 잡고 문제를 해결한다.
• Permanent generation (Java 7)
• 로드되는 클래스, 메소드 등에 관한 메타 정보 저장 고정 크기
• 리플렉션 클래스 로드 시 사용 (Spring)
• New (Young generation)
• 새로 생성한 개체가 사용하는 영역
• Minor GC 대상 영역
• Eden, From, To 요소로 구성
1) 인스턴스를 최초 생성하면 Eden 쪽에 생겨났다가 From 이나 To로 이사를 간다.
2) 남길 얘만 정하고 나머지는 전부 To로 가고 From은 flush()해서 비운다.
• Eden
• 객체 생성 직후 저장되는 영역
• Minor GC 발생 시 Survivor 영역으로 이동
• Copy & Scavenge 알고리즘
• Survivor 0, 1
• Minor GC 발생 시 Eden, S0 S0에서살아남은 객체는 S1로 이동
• S1에서 살아남은 객체는 Old 영역으로 이동
• age bit 사용 참조계수
• Old (Old generation)
• Young generation 영역에서 소멸하지 않고 남은 개체들이 사용하는 영역
• Full GC 발생 시 개체 회수 => 지연 발생
• Mark & Compact 알고리즘
JVM Garbage collector
• Heap 영역에서 사용되지 않는 객체 메모리 를 식별하고 회수하는 자동화된 메모리 관리 체계
• Mark & Sweep + Compact
• Mark : 사용되지 않는 개체 식별
• Sweep : 식별한 개체 제거
• 필요 시 Compact 실시
• Heap 영역에서 참조되지 않는 개체를 수집 및 제거해 메모리 회수
• Minor/Major(Full) GC
• GC 수행 시 프로그램 일시 정지
• stop-the-world
• GC 속도
• Minor GC가 보통 11초 이내 완료
• Full GC는 수 초 이상 진행되기도 하며 이 지연 때문에 DB 연결이 끊기는 등 운영문제 가 발생할 수 있음
살아남는 객체를 선정하는 방법
• GC는 객체 참조의 유효(Reachable) 함과 그렇지 않음(Unreachable) 을 근거로 대상 식별
• GC Roots
• Stack 데이터 => 의존성을 만든다.
• 메서드 static 데이터 => old를 만들기도 한다.
• JNI로 만들어진 데이터
Java Heap Data
'백엔드 면접' 카테고리의 다른 글
Heap 영역에 대해 ++ (0) | 2024.03.29 |
---|---|
JVM Runtime data area + (0) | 2024.03.28 |
JVM 기본 구조 (1) (0) | 2024.03.27 |
SSL인증서는 어디에 설치되는가? (0) | 2024.03.26 |
WAF와 Proxy 구조 (0) | 2024.03.25 |