본문 바로가기

JAVA

자바가 작동하는 과정 그리고 JVM?

자바가 컴파일 언어(+인터프리터) 라는 것을 알았으니, 어떻게 작동 하는지 알아보자😎

1편, 자바가 컴파일 언어? 아니면 인터프리터?🤦‍♂️

 

 

src 파일은 뭘까

 

파이썬을 할 땐 VS Code로 .py 파일만 작성하면 됐는데 자바는 프로젝트 생성하는 것부터 뭔가 이것저것 많았다. 알아보는 것을 미루고 미루다 더 이상 미루면 모래 위에 쌓은 성처럼 깊이 없이 개발하게 될 것 같아 이번 기회에 알아보았다.

 

자바의 실행 과정은 다음과 같다.

 

1. 프로젝트를 생성한 뒤, 자바 소스 코드 파일(.java)을 작성한다.

2. 소스 파일을 자바 컴파일러(javac)를 통해 바이트 코드 파일(.class)로 컴파일한다.

3. 컴파일된 목적 파일(바이트 코드)을 JVM의 클래스 로더를 통해 JVM에 올린다.

4. JVM에 있는 목적 파일들을 Execution Engine의 Interpreter와 JIT Complier를 통해 해석한다.

5. 해석된 바이트 코드는 Runtime Data Areas에 배치되어 실행된다.

 

정말 맙소사다. 하나하나 알아보자🙄🙄

 

 

프로젝트를 생성하면 다음과 같이 파일이 만들진다.

Intelli J로 프로젝트를 생성하면 .idea 폴더, src 폴더, iml 파일이 구성된다. idea 폴더는 프로젝트 관련 메타 데이터로 구성되고, src 폴더는 소스 파일, iml 파일은 IDE Module 구성에 대해 xml 형태로 표현된다.

 

여기서 메타 데이터란 데이터를 설명해주는 데이터를 의미하다. 자세한 설명은 다음 편에서 작성해봐야겠다.

 

 

1. 프로젝트를 생성한 뒤, 자바 소스 코드 파일(.java)을 작성한다.

 

일반적으로 src 폴더 내에 소스 코드 파일을 작성하면 위와 같이 클래스에 메소드를 작성할 수 있다.

 

 

2. 소스 파일을 자바 컴파일러(javac)를 통해 바이트 코드 파일(.class)로 컴파일한다.

바이트 코드의 생성

소스 파일을 실행시키면 위와 같이 out 폴더가 생성되고 production 폴더에 hello java 폴더와 목적 파일(.class)이 생성된 것을 확인할 수 있다. class 파일은 JVM(가상머신)이 이해할 수 있는 바이트 코드 파일로, javac 컴파일러를 통해 번역되어진 것이다.

 

 

3. 컴파일된 목적 파일(바이트 코드)을 JVM의 클래스 로더를 통해 JVM에 올린다.

 

출처 : https://asfirstalways.tistory.com/158

JVM은 Java Virtual Machine으로 자바 가상 머신을 의미한다. JVM의 역할은 자바 애플리케이션을 읽어 들여 자바 API와 함께 실행시키는 것이다. 자바의 장점은 운영체제에 독립적으로 구동되는 것과 메모리 관리가 잘된다는 것인데 이는 모두 JVM 덕분이다. JVM은 클래스 로더(Class Loader)와 실행 엔진(Execution Engine)으로 구성되는데 먼저 클래스 로더에 대해 알아보자.

 

https://dailyheumsi.tistory.com/196

 

클래스 로더는 바이트 코드를 JVM의 실행엔진에서 사용할 수 있도록 JVM 메모리(Runtime Data Area)의 메서드 영역(Method Area)에 적재한다. 바이트 코드는 클래스 클래스 로더를 통해 로딩(Loading), 링크(Lingking), 초기화(Initialization) 과정을 거치게 되는데, 로딩에서 바이트 코드를 읽어오면 JVM 메모리의 메서드 영역에 저장한다.

 

이때 저장하는 데이터는 FQCN(Fully-Quailified Class Name)로 이는 클래스 로더, 클래스 패키지 경로, 패키지 이름, 클래스 이름을 모두 포함한 값이다. 이 외에도 Class, Interface, Enum을 구분해서 저장하고, 메서드와 변수도 저장된다.

 

로딩이 끝나면 해당 클래스 타입의 객체를 생성해서 메모리의 힙 영역에 저장한다. 

 

 

4. JVM에 있는 바이트 코드들을 Execution Engine의 Interpreter와 JIT Complier를 통해 컴파일 실행한다.

 

실행 엔진은 JVM 메모리에 배치된 바이트 코드들을 실행한다. Interpreter, JIT compiler, Garbage Collector로 구성되며 Interpreter에서 바이트 코드 명령어를 하나씩 읽어서 해석하고 실행한다. 하지만 하나의 해석은 빠르지만 실행이 느리기 때문에 이를 보완하기 위해 JIT compiler가 도입된다.

 

JIT compiler는 인터프리터 방식으로 실행하다가도 시점에 따라 바이트 코드 전체를 컴파일해서 네이티브 코드로 변경하고 캐시에 보관한다. 이로 인해 해당 메소드는 더이상 인터프리팅하지 않고 저장된 네이티브 코드로 직접 실행하기 때문에 코드를 빠르게 수행하게 된다.

 

하지만 컴파일은 바이트 코드 하나씩 인터프리팅하는 것보다 오래걸리기 때문에 한 번만 실행되는 코드라면 인터프리팅이 훨씬 유리하기 때문에 내부적으로 해당 메서드가 얼마나 자주 수행되는지 체크하면서 일정 정도를 넘을 때 컴파일을 수행하게 된다.

 

지금까지 java 파일이 어떻게 컴파일되고 실행되는지 전체적인 과정에 대해서 알아보았다. 아직 세부적으로 알아봐야할 것들이 많다. 다음 편에서는 자바 프로젝트 생성 시 구성되는 폴더 및 파일에 대해서 알아보자.