Language/Java

JVM 구조

park_juyoung 2019. 3. 7. 01:25

 개발자가 되기위한 첫 걸음 

JVM(Java Virtual Machine)이란?

JVM은 물리적인 형태가 아닌 소프트웨어로서 하나의 개념으로 존재합니다. 이것은 "VIRTUAL"을 뜻하는 것입니다. 그리고 JVM은 독자적으로 작동할 수 있는 메커니즘과 구조를 가지고 있습니다. 이는 하나의 축약된 컴퓨터와 같은 의미에서 "MACHINE"이라는 단어가 조합된 것입니다. 


JVM은 JAVA 프로그램과 OS의 사이의 중간 다리 역활이며 JAVA 프로그램이 OS에 독립적으로 실행 될 수 있게 해줍니다.

Java Compiler를 통해 Java Source File을 ByteCode로 변환하여 JVM에 넘겨주면 JVM은 OS가 ByteCode를 이해할 수 있도록 해석 해줍니다. 


JVM 구조




 - Java Source : 사용자가 작성한 Java 코드

 - Java Compiler : Java Source 파일을 JVM이 해석할 수 있는 Java Byte Code로 변경.

 - Java Byte Code : Java Compiler에 의해 수행된 결과물 (확장자 .class 파일) 


 - Class Loader : JVM 내로 .class 파일들을 Load하여 Loading된 클래스들을 Runtime Data Area에 배치.

 - Execution Engine : Loading된 클래스의 Bytecode를 해석(interpret).

 - Runtime Data Area : JVM이라는 프로세스가 프로그램을 수행하기 위해 OS에서 할당받은 메모리 공간. 




 -  Method Area : 클래스, 변수, Method, static변수, 상수 풀( 문자 상수, 타입, 필드, 객체 참조가 저장됨) 등 이 저장되는 영역(모든 Thread가 공유)

 - Heap Areanew 키워드로 생성된 객체와 배열이 생성되는 영역이며 메소드 영역에 로드된 클래스만 생성이 가능(Garbage Collection 이슈는 이 영역에서 일어나며, 모든 Thread가 공유)

 - Stack Area : Method 내에서 사용되는 값들(매개변수, 지역변수, 리턴값 등)이 저장되는 구역으로 메소드가 호출될때 LIFO로 하나씩 생성되고, 메소드 실행이 완료되면 LIFO로 하나씩 지워진다.( 각 Thread별로 하나씩 생성)

 - PC Register : CPU의 Register와 역할이 비슷하다. 현재 수행중인 JVM 명령의 주소값이 저장된다.( 각 Thread별로 하나씩 생성)

 - Native Method Stack : 다른 언어(C/C++등)의 메소드 호출을 위해 할당되는 구역으로 언어에 맞게 Stack이 형성되는 구역. 


Heap Area 좀 더 자세히


Heap 영역은 크게 Young Generation과 Old Generation으로 나누어져 있습니다.


Young Generation은 Eden 영역과 Survivor 영역으로 구성되는데 Eden 영역은 Object가 Heap 에 최초로 할당되는 장소이며 Eden 영역이 꽉 차게 되면 Object의 참조 여부를 따져 만약 참조가 되어 있는 Live Object이면 Survivor 영역으로 넘기고, 참조가 끊어진 Garbage Object이면 그냥 남겨 놓습니다. 모든 Live Object가 Survivor 영역으로 넘어가면 Eden 영역을 모두 청소합니다. Survivor 영역은 Eden 영역에서 살아남은 Object들이 잠시 머무르는 곳입니다. 이 Survivor영역은 두 개로 구성되는데 하나의 Survivor은 반드시 비어 있는 상태로 남아 있어야합니다. 이러한 과정을 Minor GC라고 합니다.


Young Generation에서 Live Object로 오래 살아남아 성숙된 Object는 Old Generation으로 이동하게 됩니다. 성숙된 Object란 의미는 애플리케이션에서 특정 횟수 이상 참조되어 기준 Age를 초과한 Object를 말합니다. Old Generation 영역은 새로 Heap에 할당되는 Object가 들어오는 것이 아니라, 비교적 오랫동안 참조가 되어 이용되고 앞으로도 계속 사용될 확률이 높은 Object들을 저장하는 영역입니다. 이러한 과정 중 Old Generation의 메모리도 충분하지 않으면 해당 영역에도 GC가 발생하는데 이를 가르켜 Full GC(Major GC)라고 합니다.


Full GC(Major GC)에는 JDK7 기준으로 5가지 방식이 있습니다.


  • Serial GC

  • Parallel GC

  • Parallel Old GC(Parallel Compacting GC)

  • Concurrent Mark & Sweep GC

  • G1(Garbage First) GC

이중 Serial GC는 CPU 코어가 하나만 있을 때 사용하기 위해서 만든 방식입니다. Serial GC를 사용하면 애플리케이션의 성능이 많이 떨어집니다.


Serial GC


old 영역의 GC는 mark-sweep-compact이라는 알고리즘을 사용합니다. 

Old영역에 있는 참조가 없는 객체들을 표시(Mark) 하고 해당 객체들을 모두 제거(Sweep)합니다. 

그러면서 Heap 메모리 영역에 중간중간 빈 공간이 생기고 이 부분을 제거 하기 위해 각 객체들이 연속되게 쌓이도록 힙의 앞 부분부터 채워서 공간을 정리합니다.(Compact)


Parallel GC


Parallel GC는 Serial GC와 기본적인 알고리즘은 같습니다하지만 Serial GC는 GC를 처리하는 스레드가 하나인 반면 Parallel GC는 GC를 처리하는 쓰레드가 여러 개입니다. 그렇기 때문에 Serial GC 보다 빠르게 객체를 처리할 수 있습니다. Parallel GC는 메모리가 충분하고 코어의 갯수가 많을 때 유리합니다.


Permanent 영역


보통 Class의 Meta 정보나 Method의 Meta 정보, Static 변수와 상수 정보들이 저장되는 공간으로 흔히 메타데이터 저장 영역이라고 합니다.

이 영역은 Java 8부터는 Native 영역으로 이동하여 Metaspace영역으로 변경되었습니다.

기존 Prem 영역에 존재하던 Static Object는 Heap 영역으로 옮겨져서 GC의 대상이 될 수 있도록 하였습니다.

이유는 Perm 영역이 꽉 차면 OOM(Out Of MemoryError)이 발생 하기 때문에 이 해결 방안으로 이러한 해결 방안이 나오게 되었습니다.

(Heap 영역은 JVM에 의해 관리된 영역이며, Native 메모리는 OS 레벨에서 관리하는 영역으로 구분)


마무리


GC를 실행하기 위해 JVM이 애플리케이션 실행을 멈추는 것을 stop-the-world라 한다. stop-the-world가 발생하면 GC를 실행하는 쓰레드를 제외한 나머지 쓰레드는 모두 작업을 멈춘다. GC 작업을 완료한 이후에야 중단했던 작업을 다시 시작한다. 어떤 GC 알고리즘을 사용하더라도 stop-the-world는 발생한다. 대개의 경우 GC 튜닝이란 이 stop-the-world 시간을 줄이는 것이다.


관련글

1. https://12bme.tistory.com/382

2. https://d2.naver.com/helloworld/1329

 



 

내용이 도움이 되셨거나 초보 블로거를 응원하고 싶으신 분은 아래 하트♥공감 버튼을 꾹 눌러주세요! 

내용의 수정이 있거나 도움이 필요하신 분은 댓글을 남겨주세요!





'Language > Java' 카테고리의 다른 글

예외 처리(Exception)  (0) 2019.03.21
컬랙션 프레임워크란?  (0) 2019.03.20
RxJava란? -4 Scheduler  (0) 2019.01.26
RxJava - 3 Operators 이어서  (0) 2019.01.26
RxJava란 - 2 Operators  (0) 2019.01.26