JVM 이란 

Java Virtual machine의 약자로 자바를 실행하기 위한 가상머신이라고 할 수 있다. 

 

JVM이 일하는 순서 

실행될 클래스 파일을 메모리에 로드 -> 초기화 작업수행 

메소드와 클래스 변수들을 해당 메모리영역에 배치 

클래스로드가 끝나면 JVM은 main 메소드를 찾아 지역, 객체, 참조 변수를 Stack에 쌓는다.

이제 다음 라인을 진행하면서 상황에 맞는 작업을 이어간다. (함수호출, 객체할당 등) 

 

 

JAVA 코드를 JVM 으로 실행시키는 과정을 설명하면,

자바 컴파일러에 의해 코드가 클래스 파일로 컴파일된 후 클래스로더로 해당 클래스 파일들을 업로드 시킨다. 

이후 로딩된 바이트 코드를 실행 엔진을 이용하여 해석(interpert)하여 런타임 데이터 영역에 배치시킨다. 

하지만 매번 한줄씩 해석하는데는 시간이 오래걸리기 때문에 JIT (Just In Time) 컴파일러를 이용한다. 

JIT를 사용하지 않는다면 바이트코드를 사용할때마다 interpert 해야하기 때문에 속도가 매우 느리다. 

그래서 적절한 시점에 JIT 컴파일러가 바이트 코드를 컴파일해 네이티브 코드로 캐싱해놓는다. 

여기서 컴파일한다는 것은 인터프리터처럼 한줄 단위로 컴파일 하는것이 아니라 실행하는 전체 코드를 

컴파일하고 캐시하므로 이 또한 시간이 꽤 걸린다. 하지만 한번 컴파일 된 후에는 캐싱이 되니 빠른 실행을 

보장할것이다. 한번 실행되고 말것을은 인터프리터로 처리하고 주기적으로 수행하는 것은 JIT로 컴파일 한다. 

 

이렇게 해석된 코드들은 Runtime Data Areas에 배치되어 실질적인 수행이 이루어지게 된다.

이러한 과정속에서 필요에따라 JVM은 Thread Synchronization 과 GC(Garbage Collection)같은 작업을 수행한다. 

 

 

*Runtime Data Areas : JVM이 프로그램을 수행하기 위해 OS로 부터 별도로 할당받는 메모리 공간이다. 

 

 

Runtime Data Area의 구조 

- 크게 다섯가지 영역으로 나누어 진다.

 

1. PC Register

Thread가 시작될 때 생성되며 생성되는 쓰레드마다 하나씩 존재한다.

Thread가 어떤 명령을 실행해야할지 기억하는 부부능로 현재 수행중인 JVM명령의 주소를 갖는다. 

 

 

2. JAVA Virtual Machine Stack 

프로그램 실행 과정에서 임시로 할당되었다가 메소드를 빠져나가면 바로 소멸되는 특성의 데이터를 

저장하기 위한 영역이다. 각종 변수나 임시데이터, 스레드나 메소드의 정보를 저장한다. 메소드 호출시마다 

각각 스택프레임(메소드를 위한 공간)이 생성되고 수행이 끝나면 프레임별로 삭제한다. 

 

3. Native Method Stack 

JAVA 프로그램이 컴파일 되어 생성되는 바이트코드가 아닌 실제 수행할 수 있는 기계어로 작성된 프로그램을 

실행시키는 영역이다. 

 

4. Method Area( Class area = Stack Area) 

모든 스레드가 공유하는 메모리 영역으로 클래스, 인터페이스 메소드, 필드, Stack 변수 등의 바이트 코드를 보관한다. 

자바 프로그램은 main 메소드의 호출에서부터 흐름을 이어가기 때문이다. 

 

5. Heap

객체를 저장하는 가상메모리 공간, 프로그램상에서 런타임시 동적으로 할당하여 사용하는 영역이다. 

클래스에서 Instance를 생성하면 heap에 저장되고 new 연산자로 생성된 객체와 배열을 저장한다. 

 

 

 

 

자, 쉽게 정리하자면

 

프로그램을 start한 시점부터 생각해보자.

 

프로그램을 스타트하면 JVM은 우리가 작성한 코드들을 기계어로 바꾸기 위해 컴파일 작업을한다.

 

이렇게 컴파일된 코드들은 실행하기 위해 어딘가에 기억할 공간이 필요할것이다. 

우리가 코드를 작성할 때 메소드에 작성하듯 JVM도 실행할 코드들을 컴파일한 후 메소드 영역에 올려놓는다.

 

메소드 영역에는 우리가 작성한 클래스, 메소드, 인터페이스, 필드, Stack 변수 등을 기억하는 것이다.

 

실행할 코드들이 준비되었다면 이제 실행할 차례이다.

main 메소드를 시작으로 우리가 작성한 코드는 흐름에 따라 메소드를 호출하기도하고

연산도 이루어지고 임시로 저장되는 값도 생겨날 것이다.

 

여기서 잠깐 Stack 구조를 생각해보자, 스택은 마지막 들어온 데이터가 먼저 나간다.

그리고 Stack의 대표적인 사용예로 실행취소(Ctrl +z)와 같은 기능을 구현할때 사용한다고 한다. 

 

메소드가 실행되는 흐름을 생각해 본다면 이 구조와 비슷하다는 점을 알 수 있을것이다. 

 

고로, 이렇게 연산되는 과정에 임시 저장되는값들, 메소드가 소멸되면 사라지는 데이터들이 

Stack 영역에 저장된다고 기억하면 된다. 

 

 

Heap은 객체와 배열이 생성되는 영역이다. 

사전적인 의미에서 heap은 무엇인가를 쌓아올린 더미를 뜻한다. 

단어 자체의 의미와 비슷하게 실행되는 메소드에서 생성한 객체와 배열들을 Heap에 저장해두고 

필요할 때 찾아서 쓴다고 생각하면 될것같다. 

 

 

 

 

 

 

 

참고 

https://javarevisited.blogspot.com/2013/01/difference-between-stack-and-heap-java.html

https://www.journaldev.com/2856/java-jvm-memory-model-memory-management-in-java

https://cafe.naver.com/jjdev/227

+ Recent posts