2.5회독을 통해 읽었다.
책을 읽을때마다 어려워서 넘겼던 내용들이 보이기 시작하고, 이해가 되기 시작했다.
CS적인 측면에서 설명이 좋다
새로운 시야를 알게해주는것 같다.
1장은 PASS
2장
런타임 데이터 영역 :
- PC 레지스터 : 스레드 복원에 사용, 자바메서드의 줄번호 표시기
- 가상 머신 스택 : 스레드와 라이프사이클이 같다. 데이터타입,객체참조,반환주소타입. 지역변수테이블은 컴파일 시점에 고정된다. 슬롯은 32비트 단위
- 네이티브 메서드 스택
- 힙 : 모든 스레드가 공유. 인스턴스, 배열 저장. 할당 효율을 위해 스레드 로컬 할당버퍼 여러개 존재. 논리적으로 연속
- 메서드 영역(런타임 상수 풀) : 모든 스레드가 공유. 타입정보, 상수, 정적 변수, JIT의 코드 캐시
- 런타임 상수 풀 : 클래스 버전, 필드, 메서드, 인터페이스 / 리터럴과 심벌 참조
객체의 생성 - new를 만나면 클래스가 로딩여부 확인, 메모리 공간 검색 후 할당(원자적으로 하기 or 스레드별 할당 버퍼), 객체헤더 제외하고 나머지공간 0으로 초기화, 객체헤더에 설정정보 저장 /// 이후 생성자 실행(invokespecial).
즉, new는 바이트코드에서 new(JVM에서 객체 생성)와 invokespecial(생성자 실행)로 나뉜다.
객체의 메모리 레이아웃 : 객체헤더-마크워드, 클래스워드, 배열길이 / 인스턴스 데이터 / 정렬 패딩
객체 접근 방식
- 핸들 : 핸들풀을 통해 객체인스턴스 + 객체 타입 데이터 연결 -> 이중으로 이동이지만, GC시 핸들에서 인스턴스 포인터만 변경
- 다이렉트 : 스택에서는 인스턴스로 바로 연결, 자바 힙의 객체에서 인스턴스 데이터 뿐만 아니라, 객체 타입 데이터 주소도 있어야한다.(핫스팟은 다이렉트 사용)
덤프의 종류에는 쓰레드덤프와 힙덤프가 있음
힙덥프로 메모리 누수를 잡아보기
3장
GC대상을 판별하는 방법들
- 참조 카운팅 : 객체의 참조카운트를 통해 판별. 순환참조를 계산하기 어렵다
- 도달 가능 분석(GC 루트) : GC루트는 [JVM 스택, 클래스 정적 필드, 상수 객체, JNI의 참조 객체, JVM 내부 참조, 락 객체, 콜백, 로컬 코드 캐시, 등]
- 사망선고 : GC단계에서 도달불가 객체들에게 finalize()를 2번째 호출하려고하면, 죽인다. 첫번째 finalize()에서 다른 인스턴스 변수나, 객체에 this를 할당하는식으로 구원이 가능하다. 해당 동작은 앱레벨에서 사용하지 말것
- 메서드 영역 회수 : 더이상 사용되지 않는 상수(리터럴 회수 ex.String)와 클래스(해당 클래스의 인스턴스가 모두 회수, 클래스 로더 회수, Class 객체 참조 x, 리플랙션 메서드 이용x -> 모두 만족시 클래스 회수 허용) => 리플랙션, 동적프록시, CGLIB가 많이 쓰일때, 메서드영역의 부담을 줄이기 가능
- 세대 단위 컬렉션 : 신세대와 구세대.
1. 대다수 객체는 읽찍 죽는다.
2. GC과정에서 살아남은 횟수가 클수록 더 오래 살아남을 가능성이 커진다.
3. 세대간 참조는 같은 세대간 참조보다 훨씬 적다.
-> 신세대가 세대간 참조를 가질때, 구세대로 승격될 것이다. 이를 통해 신세대에 기억 집합을 두고, 구세대를 조각으로 나눈뒤, 어느 조각에 세대간 참조가 있는지 기록한다. 이 블록의 객체만 마이너 GC시 GC루트에 추가된다.
마크-스윕 알고리즘
- 회수 객체를 표시, 이후 표시객체를 쓸어 담음
- 실행효율이 일정하지 않음, 메모리 파편화가 심함
마크-카피 알고리즘
- 가용 메모리를 두 구역으로 분할, 한 번에 한 블록만 사용
- 한 블록이 가득차면, 살아남는 객체만 다른 블록에 복사, 기존 블록은 청소
- 가용메모리가 절반으로 줄어들고, 복사에 오래걸리는 단점
- 신세대에 이 알고리즘을 적용(대다수 객체가 제거되고, 소수의 객체만 복사하면 되기 때문)
아펠 스타일
- 신세대를 큰 에덴과 두개의 생존자 공간, 메모리 할당시에는 생존자1과 에덴만 사용
- GC시에 에덴과 생존자를, 사용안한 생존자2로 복사, 이전 에덴과 생존자는 청소
- 에덴 80%, 생존자 10% 10%로 구성하여, 가용메모리의 90%를 사용함
- 10%이상의 객체가 생존한다면, 구세대로 이동
마크-컴펙트 알고리즘
- 구세대의 생존 특성을 감안, 표시단계는 마크-스윕과 동일하나, 다음 컴펙트 과정에서 메모리 한쪽으로 모은다. 해당 이동은 STW에서 수행된다. 그러나 컴펙션이 없으면 할당링크드리스트로 읽어야하고, 부담이 커질 수 있다.
- 일시정지를 할수록, 처리량은 올라간다.
'책' 카테고리의 다른 글
[책] Android 개발자 도서 추천 (0) | 2025.02.25 |
---|---|
[책] 인프라/데브옵스 도서 목록&후기 (2) | 2025.01.02 |
[책] 백엔드 개발자 도서 목록&후기 (0) | 2025.01.01 |
[Go] 러닝 Go 후기 (0) | 2024.11.24 |