[Java] JVM을 파헤쳐보자: 1. 메모리 구조와 멀티스레드
JVM이란?
자바를 공부하는 사람이라면 JVM에 대한 이야기를 많이 들어보았을 것이다. JVM이란 Java Virtual Machine의 약자로, 자바로 작성된 프로그램을 실행시켜주기 위한 가상 머신(가상의 컴퓨터, 컴퓨터안의 컴퓨터)이다.
JVM은 Java를 플랫폼 독립적인 언어로 만들어준다는 특징과, 메모리를 관리하고 최적화 해주는 기능이 존재한다는 특징이 존재한다.
여기서 플랫폼 독립적이라는건, 어떤 운영체제 상에서 작성된 프로그램이든 모두 문제없이 돌아간다는 것인데, 이를 가능토록 중개해주는 것이 바로 JVM의 역할이다. 또한 Java이전에는 프로그램 메모리를 모두 SW개발자가 관리했다면, JVM은 가비지 컬렉터를 통해 자동으로 메모리 관리를 해준다! 따라서 개발자는 운영체제에 맞는 JVM만 깔아주게 되면, 어느 OS위에서 작성한 프로그램이든 문제없이 구동할 수 있으며, 메모리 관리도 해주는것.
하지만 모든건 제대로 알고 써야한다. 따라서, 앞으로 몇개의 게시글을 거쳐 JVM에대해 끝까지 파헤쳐보도록하자.
JVM의 메모리 구조
JVM의 메모리 구조는 다음과 같은 것들로 구성되어 있다.
1. Class Loader
클래스 파일들을 엮어 JVM내부의 메모리 영역인 Runtime Data Area로 적재하는 역할을 수행한다. 자바 애플리케이션이 실행 중 일때 이런 작업이 수행된다
2. Excution Engine
메모리에 적재된 클래스들을 기계어로 변경해, 명령어의 단위로 실행시켜주는 역할을 한다. 이때 JVM내부에서는 인터프리터 방식과, JIT 컴파일러 방식 두가지 모두 사용한다. 또한 GC가 이 영역에 포함되어 있다.
3. Garbage Collector(GC)
메모리 영역중 Heap영역에 존재하는 객체들중에 참조되지 않아 unreachable한 상태에 빠진 객체들을 탐색 후 제거하는 역할을 수행한다. Execution Engine에 속해있는 기능이다.
4. Runtime Data Area
JVM의 메모리 영역으로 총 5가지로 나뉜다
- Method Area
클래스의 필드 정보와 메소드 정보, static변수(전역 변수)등 Class에 대한 바이트코드가 저장이되는 영역이다. JVM이 어떤 메소드를 호출하기 위해서는 해당 메소드들에 대한 클래스 파일의 바이트코드가 반드시 Method Area에 적재되어 있어야 한다! - Heap
new 키워드로 생성된 객체와 배열 등이 저장되는 구역이다. GC의 대상이 되는 구역이 되어 주기적으로 사용하지 않는 메모리 해제가 일어난다. - Stack Area
지역 변수, 파라미터 등 어떤 메소드를 실행 시켰을때 사용되는 임시 값들이 생성되는 영역으로 해당 함수 호출이 종료될때마다 stack에서 제거된다.
스택 영역에 차례대로 저장되는 함수의 호출을 stack frame이라 부른다 (아래 사진 참조)
- PC Register
JVM은 멀티스레드의 환경이기에 스레드간 전환이 일어날때 각 스레드의 상태를 저장해줄 필요가 있다.
PC register가 바로 하나의 스레드가 실행되고 있는 부분, 주소와 명령 등을 저장하는 영역이다. - Native Method stack
c++/c 등의 언어로 작성된 코드가 저장되는 영역이다.
JVM의 멀티스레드
자바 애플리케이션은 프로그램을 의미하는데, 이런 자바 애플리케이션을 컴파일하여 실행시키면 하나의 JVM 프로세스가 실행이된다.
즉, 하나의 JVM은 프로세스 단위라고 할 수 있으며, 내부에는 여러개의 스레드들이 실행될 수 있음을 의미한다.
프로세스와 스레드가 궁금하다면 이 게시글을 클릭해서 읽어보자
그렇다면 JVM 프로세스가 멀티스레드 환경일때 각 스레드들은 어떤 영역을 공유할까?
각 스레드는 Method와 Heap영역을 공유하고 독자적인 Stack, PC 레지스터, native method 영역을 가진다.아래의 사진을 참고해보면 이해하기가 쉽다.