JVM GC

JVM


1) 프로그램이 실행되면 JVM은 OS로부터 이 프로그램이 필요로 하는 메모리를 할당받는다.
JVM은 이 메모리를 용도에 따라 여러 영역으로 나누어 관리한다.
2) 자바 컴파일러(javac)가 자바 소스코드(.java)를 읽어들여 자바 바이트코드(.class)로 변환시킨다.
3) Class Loader를 통해 class파일들을 JVM으로 로딩한다.
4) 로딩된 class파일들은 Execution engine을 통해 해석된다.

  • Execution engine : byte 코드를 읽으며 실행한다.
  • byte code -> OS에서 실행할 수 있는 기계어로 변환한다.
  • 인터프리터 : 바이트 코드를 한줄 씩 실행
  • 바이트 코드를 한줄 씩 컴파일 후 실행하는 것 -> 같은 코드를 계속 변환하는 것은 낭비 -> JIT 컴파일러 사용
  • JIT 컴파일러 : 실행 시점에서 인터프리트 방식으로 기계어 코드를 생성하면서 그 코드를 캐싱하여, 같은 함수가 여러 번 불릴 때 매번 기계어 코드를 생성하는 것을 방지한다.
  • 컴파일러 : 1) 정적 컴파일러, 2) 동적 컴파일러 (:JIT 컴파일러)
  • 컴파일, 인터프리트
    • 둘 다 code를 기계어로 변환하는 것
    • 컴파일: 전체 code를 기계어로 변환한다.
    • 인터프리트: code를 line by line으로 변환한다.

인터프리티드 언어는 특별한 플랫폼 의존성을 가질 필요가 없다. 실행중에 ‘interpreted’ 되므로, 적절한 interpreter만 있다면 어떤 기종에서도 잘 실행될 수 있는 것이다. 이런 이유로 인터프리티드 언어는 보다 더 크로스플랫폼적 성격을 갖게 된다.


요런 게 byte code.


JVM 메모리 구조

  • 모든 Thread에 공유되는 영역: method area, heap

  • Method Area

    • byte code가 저장된다.
    • 클래스 정보, 변수 정보, static 변수
  • Heap

    • 동적으로 생성된 객체
    • GC 대상
  • PC 레지스터

    • 스레드가 시작될 때 생성
    • 현재 수행중인 JVM 명령어
  • Native Method
    * [JAVA가 아닌 다른 언어로 작성된 코드를 위한 공간](https://stackoverflow.com/questions/18900736/what-are-native-methods-in-java-and-where-should-they-be-used)
    JIT 컴파일러가 만든 네이티브 코드도 여기에 들어가는 건가?

자바 메모리 구조

  • static
    • 프로그램 시작~종료까지 살아있다.
    • static 메서드 클래스 생성/초기화없이 사용하는 것
  • stack
    • 기본 자료형 (int,char)
    • Thread마다 생긴다. : 독립적
    • method별로 stack frame이 생성된다.
  • heap
    • 참조형 (인스턴스, 배열)
    • 주소를 stack이 가지고 있다.
    • Thread끼리 공유한다.
      method area : 정적인 자원

Stack

  • 메서드마다 satck frame이 생성된다.
    • 생성자도 메서드, 생성자에 해당하는 stack frame이 생성된다.
    • 다음 라인에서는 생성자의 stack frame이 없어진다.
  • stack frame에는 operand 영역와 변수 영역이 있다.
    • opcode에 따라 byte 코드를 실행한다.
    • 연산할 때에는 operand 영역에서 수행된다.
      자바지기
  • single instance
public class Controller {
	private QuestionDao questionDao = QuestionDao.getInstance();
    	// dao : 상태없으니까 갠츈
    	// private Question question; // 1) 싱글 instance 안에 있는 필드 변수 : 멀티쓰레드 환경에서 동시접근하며 문제 발생 가능

	public void doSomething() {
    		Question question;
            	// 2) 여기는 stack 영역이기 때문에 1)과 달리 멀티쓰레드 환경에서 동시접근 문제 X
    	}
    

GC

Mark And Sweep

GC에서 사용하는 알고리즘

Mark

Reachable, Unreachable 식별하는 것

Reachable: 사용중, Unreachable: 사용중이지 않은
Reachable ↔ Unreachable : Rootset과 관계 있으면 reachable
Rootset: 프로그램에서 직접적으로 도달가능한 객체의 집합
1. stack 영역 데이터
2. static
3. JNI

  • Native Method Interface
    JVM에 의해 실행되는 코드 중 네이티브로 실행하는 것이 있다면 해당 네이티브 코드를 호출하거나 호출될 수 있도록 만든 일종의 프레임워크


여기서 빨간 색은 unreachable한 것이다.

Sweep

Unreachable한 객체를 heap에서 제거한다.

Compact

메모리 최적화

메모리 최적화란? 사용 가능한 메모리가 존재하지만 할당 불가능한 문제 해결

  • Internal Fragmentation
    메모장에 4kb 메모리가 할당되었는데, 1kb만 사용하고 3kb를 사용하지 않는다.
  • External Fragmentation
    할당&해제 과정에서 메모리가 듬성 듬성 할당되어있을 때

Minor GC

Young Generation에 대한 GC

  • Eden이 다 찼을 때 발생한다.
  • Mark Ans Sweep, (Compact)
  • Survivor 0 <-> 1 둘 중 하나만 사용할 수 있다.
  • 이동하면서 age가 증가한다.
  • 특정 임계값에 도달하면 Old Generation으로 이동한다.

Major GC

Old Generation에 대한 GC
Old Generation이 다 차면 Mark and Sweep, (Compact)를 한다.


Stop the world

GC를 실행할 때 JVM이 애플리케이션 실행을 멈추는 것
: GC를 실행하는 쓰레드 외에 모든 쓰레드가 작업을 중단한다.

Serical GC

싱글스레드로 GC 처리한다.

Parallel GC

Young Generation 영역을 멀티쓰레드로 GC 처리한다.

Parallel Old GC

Old Generation도 멀티쓰레드로 GC 처리한다.

CMS GC

compact하지 않는다.
stop the world를 줄이기 위해 고안

G1 GC

엘리 테코톡을 보고 정리한 자료입니당~

좋은 웹페이지 즐겨찾기