본문 바로가기

프로그래밍/JAVA

자바 프로그램 실행과정 & 자바 메모리구조

자바로 개발하는데있어서 반드시 알아야 개발하는것은 아니지만 기본적으로 어떻게 ~.java파일이 돌아가는지 생각해볼 필요도있고, 거의 드물겠지만 classLoader를 개발시 직접 사용하게될때 알면 좋으니.. 정리해보았다.(입사초에 사수께서 알아보라고했던게 시작이였는데.. 잘 이해가 안가서 그냥 지나갔다가 다시보고 또 지나갔다가 다시보고 했었다.. 여전히 완전히 이해안가는부분이있다..)






자바 프로그램 실행과정


1. 프로그램이 실행되면 JVM(Java Virtual Machine : 자바가상머신) OS로부터 이 프로그램이 필요로 하는 메모리를 할당받는다. (JVM에 대한 자세한 설명은 밑으로..!)


2. 자바 컴파일러(javac)가 자바 소스코드(.java)를 읽어들여 자바 바이트코드(.class)로 변환시킨다.


3. JVMClass Loader를 통해 class파일들을 로딩한다.


4. 로딩된 class파일들은 JVM의 Execution engine을 통해 해석된다.


5. 해석된 바이트코드는 Runtime Data Area 에 배치되어 실질적인 수행이 이루어지게 된다. , JVMmain 메소드를 찾아 한줄한줄씩 읽어나가며 method area, heap area, stack area 등에 셋팅!

이러한 실행과정 속에서 JVM은 필요에 따라 Thread Synchronization GC같은 관리작업을 수행한다.



세부적으로 Runtime Data Area를 살펴보자면..





Runtime Data Area


-Method Area(Class Area=Static area)

클래스 로딩시 클래스 정보를 저장하는 메모리 공간


*클래스 로딩이란?

-클래스를 사용하는 시점에 해당 클래스의 바이트코드가 들어있는 파일을 찾아서 메모리(method area)에 로딩하는것을 말함


**클래스 로딩이 왜 이뤄지나?

-클래스의 메소드를 호출하기위해서는 클래스파일이 메모리에 로딩되어있어야한다. 그래서 클래스클 실행할 때, *.class파일을 찾아서 메모리에 로딩하는것이다.

 

***클래스 로딩과정

1.     어떤 메소드를 호출하는 문장을 만났는데, 그 메소드를 가진 클래스 바이트코드가 아직 로딩된 적이없다면, 곧바로 JVM JRE라이브러리 폴더에서 클래스를 찾음.

2.     없으면, CLASSPATH 환경변수에 지정된 폴더에서 클래스를 찾음.

3.     찾았으면 그 클래스 파일이 올바른지 바이트코드를 검증한다.

4.     올바른 바이트코드라면 메소드영역으로 파일을 로딩한다.

5.     클래스 변수를 만들라는 명령어가 있으면 메소드 영역에 그 변수를 준비한다.

6.     클래스 블록이 있으면 순서대로 그 블록을 실행한다.

7.     이렇게 한번 클래스의 바이트코드가 로딩되면 JVM이 종료될때까지 유지된다.

 

간단하게 말하자면 클래스가 로드되면(클래스내 전역변수, 정적멤버변수(static붙은 자료형), static영역에 데이터 저장한것들) 프로그램의 시작부터 종료가 될때까지 Method Area 영역에 남아있게된다.


-Heap Area

참조변수가 가리키고 있는 인스턴스가 실제저장되어있는공간(new키워드를 사용함)

 

-Stack Area

지역변수와 매개변수가 저장,, 프로그램 실행과정에서 임시로할당되고 그게 끝나면 바로 소멸되는것들이 저장,, 위의 참조변수도 stack

 

-PC Reigister

Thread 가 시작될 때 생성되며 생성될 때마다 생성되는 공간으로 스레드마다 하나씩 존재한다. Thread가 어떤 부분을 어떤 명령으로 실행해야할 지에 대한 기록을 하는 부분으로 현재 수행 중인 JVM 명령의 주소를 갖는다.

(보통 CPU가 명령어를 처리 하는 과정에서 수행하는 동안 필요한 정보를 Register라는 CPU내의 기억장치에 저장해 둔다. 이는 CPU에 종속적 일 수 밖에 없다. 그렇기 때문에 자바의 철학을 실현하기 위해서는 이러한 CPU내의 Register의 역할을 JVM상에 논리적인 메모리 영역으로 구현한다.

출처: https://romanticcode.tistory.com/43 [개발과 낭만이 있는곳] )

 

-Native Method Stack

자바 프로그램이 컴파일되어 생성되는 바이트 코드가 아닌 실제 실행할 수 있는 기계어로 작성된 프로그램을 실행시키는 영역이다. JAVA가 아닌 다른 언어로 작성된 코드를 위한 공간이다.

 

※PC Register, Stack, Native Method Stack은 각 스레드마다 생성이 되지만,

HeapMethod Area는 모든 스레드가 공유하게된다




JVM구성

(jvm은 아직 제대로 공부를 못해보아서.. 설명이 잘 되어있는 사이트에서 발췌하였다. 출처 : http://asfirstalways.tistory.com/m/158


-Class Loader(클래스 로더)

JVM내로 클래스(.class파일)를 로드하고, 링크를 통해 배치하는 작업을 수행하는 모듈이다. Runtime 시에 동적으로 클래스를 로드한다. jar파일 내 저장된 클래스들을 JVM위에 탑재하고 사용하지 않는 클래스들은 메모리에서 삭제한다. (컴파일러 역할) 자바는 동적코드, 컴파일 타임이 아니라 런타임에 참조한다. , 클래스를 처음으로 참조할 때, 해당 클래스를 로드하고 링크한다는 것이다그 역할을 클래스 로더가 수행한다.

 

-Execution Engine(실행 엔진)

클래스를 실행시키는 역할이다. 클래스 로더가 JVM내의 런타임 데이터 영역에 바이트 코드를 배치시키고, 이것은 실행엔진에 의해 실행된다. 자바 바이트코드는 기계가 바로 수행할 수 있는 언어보다는 비교적 인간이 보기 편한 형태로 기술된 것이다. 그래서 실행 엔진은 이와 같은 바이트코드를 실제로 JVM내부에서 기계가 실행할 수 있는 형태로 변경한다. 이 때 두 가지 방식을 사용하게 된다.

 

-Interpreter(인터프리터)

실행 엔진은 자바 바이트 코드를 명령어 단위로 읽어서 실행한다. 하지만 이 방식은 인터프리터 언어의 단점을 그대로 갖고 있다. 한 줄 씩 수행하기 때문에 느리다는 것이다.

 

-JIT(Just - In - Time)

인터프리터 방식의 단점을 보완하기 위해 도입된 JIT 컴파일러이다. 인터프리터 방식으로 실행하다가 적절한 시점에 바이트코드 전체를 컴파일하여 네이티브 코드로 변경하고, 이후에는 해당 더 이상 인터프리팅 하지 않고 네이티브 코드로 직접 실행하는 방식이다. 네이티브 코드는 캐시에 보관하기 때문에 한 번 컴파일된 코드는 빠르게 수행하게 된다. 물론 JIT컴파일러가 컴파일하는 과정은 바이트코드를 인터프리팅하는 것보다 훨씬 오래걸리므로 한 번만 실행되는 코드라면 컴파일하지 않고 인터프리팅하는 것이 유리하다. 따라서 JIT 컴파일러를 사용하는 JVM들은 내부적으로 해당 메서드가 얼마나 자주 수행되는지 체크하고, 일정 정도를 넘을 때에만 컴파일을 수행한다.

 

-Garbage collector

GC를 수행하는 모듈 (쓰레드)이 있다.



참고사이트 : https://hoonmaro.tistory.com/19http://asfirstalways.tistory.com/m/158