JVM 밑바닥부터 파해치기책을 정리한 내용이며, 모든 내용은 해당 도서 기반입니다.

1부 자바와 친해지기

1장 자바 기술 시스템 소개

1.1 들어가며

  • 하드웨어 플랫폼 족쇄 제거
  • 안전한 메모리 관리 시스템
  • 런타임 핫코드 감지, 컴파일 최적화하며 최상의 성능 도움
  • 표준 api도 풍부하고 서드파티 라이브러리도 많다.

이번 장에는 자바 시스템의 구성요소, 역사, 자바의 현재와 미래를 다룬다.

1.2 자바 기술 시스템

  • 크게는 아래를 포괄한다
    • 자바 프로그래밍 언어
    • 가상 머신 구현
    • 클래스 파일 포맷
    • 클래스 라이브러리 api (표준 api)
    • 오픈소스 클래스 라이브러리
  • 언어, vm, 클래스 라이브러리를 묶어 jdk라고 한다, 또한 java se api, vm, 배포기술까지를 묶으면 jre라고한다.

1.3 자바의 과거 와 현재

방대한 역사속에 다양한 jvm구현체들과 소송들을 소개하고 미래를 향한 움직임도 소개한다. 재미있게 읽었고, 다시 알아야한다면 다시 보면 될 내용이라 정리하지는 않았다. 그중 기억나는 일부만 정리한다.

  • Hello World 실행에도 100mb가 넘는 jre
  • 마이크로 서비스에 맞지 않는 언어
    • 구동시간이 길고 최고성능을 내기까지 예열이 필요 (잦은 배포와, 고가용성 서비스에 불리)
    • 서버리스 아키텍처에서 이런 모순이 두드러짐

2부 자동 메모리 관리

2장 자바 메모리 영역과 메모리 오버플로

2.2 런타임 데이터 영역

Image

2.2.1 프로그램 카운터

  • 프로그램 카운터 레지스터는 작은 메모리 영역으로 현재 실행중인 스레드의 ‘바이트 코드 줄 번호 표시기’라고 생각하면 쉽다.
  • 바이트코드 인터피르터는 이 카운터 값을 바꿔 다음에 실행할 바이트코드 명령어를 선택하는식으로 동작
  • 프로그램의 제어 흐름, 분기, 순환, 점프등을 표현
  • 예외처리나 스레드복원같은 기능이 이 표시기를 활용해 동작
  • jvm의 멀티스레딩은 cpu코어를 여러 스레드가 교대로 사용하는 방식으로 구현되기 때문에, 특정 시각에 한 코어는 한 스레드의 명령어만 실행하게 된다. 따라서 스레드 전환 후 이전에 실행하다 멈춘 지점을 정확하게 복원하려면 스레드 각각에는 고유한 프로그램 카운터가 필요하다.
  • 따라서 각 스레드의 카운터는 서로 영향을 주지 않는 독립된 영역에 저장된다. 이 메모리 영역을 프라이빗 메모리라고 한다.
  • 스레드가 자바 메서드를 실행중일 때는 실행중인 바이트코드 명령어의 주소가 프로그램 카운터에 기록된다.
  • 한 편 스레드가 네이티브 메서드를 실행중일 때 프로그램 카운터 값은 undefined다 프로그램 카운터 메모리 영역은 oom 조건이 명시되지 않은 유일한 영역이기도 하다.

2.2.2 자바 가상 머신 스택

  • 마찬가지로 스레드 프라이빗하며, 스레드와 수명주기가 같다.
  • 가상머신스택은 메서드를 실행하는 스레드의 메모리 모델을 설명해준다.
  • 메서드 호출시 스택프레임만들고, 지역변수 테이블, 피연산자 스택, 동적 링크, 메서드 반환값등의 정보를 저장한다.
  • 그다음 스택프레임을 가상머신 스택에 푸시하고, 메서드가 끝나면 팝하는일을 반복한다.
  • 지역 변수 테이블에는 jvm이 컴파일타임에 알수있는 다양한 기본데이터타입, 객체 참조, 반환주소 타입을 저장한다.
  • 이걸 저장하는 공간을 지역 변수 슬롯이라 하고 슬롯의 크기는 일반적으로 32비트이다.
  • 지역 변수 테이블을 구성하는데 필요한 데이터 공간은 컴파일 과정에 할당된다. 자바 메서드는 스택프레임에서 지역변수용으로 할당받아야 할 공간의 크기가 이미 완벽하게 결정되어있다.

2.2.3 네이티브 메서드 스택

  • jvm 스택과 비슷!
  • 네이티브 메서드를 사용할때 실행된다. (보통 다른 언어로 작성된 메서드, jni를 통해 호출됨, 즉 jvm이 직섭 실행할수없는 네이티브 코드를 실행하기 위한 메서드)

2.2.4 자바 힙

  • 모든 스레드 공유
  • 다른 언어의 힙과 동일
  • 거의 모든(사실상 모든)객체가 힙에 저장됨.
  • gc가 관리하는 메모리 영역이기에, gc힙이라고 함
  • 객체 할당 효율을 높이고자 스레드 로컬 할당 버퍼 여러개로 나뉜다. (그래도 모든 객체가 힙에 저장된다는 사실은 마찬가지, 일부 메모리회수와 할당을 조금 더 빠르게 하기위해 일정한 세부영역이 있을 뿐)
  • 힙은 물리적으로 떨어진 메모리에 위치해도 상관없으나 논리적으로는 연속되어야 한다.

2.2.5 메서드 영역