03. JAVA 빌드 과정

thsamajiki·2022년 10월 25일
0

JAVA

목록 보기
3/24

03. JAVA 빌드 과정

JVM 동작 과정

JVM의 탄생 배경

JAVA의 아버지라고 불리우는 제임스 고슬링은 가전제품 내에 탑재하는 프로그램을 C/C++로 개발하던 사람이었다. 가전제품 특성 상 매우 다양한 하드웨어를 가지고 있고 각각의 하드웨어에 맞는 프로그램을 개발하는 것이 번거로워서 JAVA를 개발하게 되었다고 한다.

이러한 배경 덕분에 JAVA의 큰 특징 중 하나가 플랫폼에 독립적이라는 점이다. 플랫폼에 독립적이라는 특징 덕분에 많은 사람들의 인기를 끌게 되었고 요즘도 가장 많이 사용하는 언어 중 하나이다.

플랫폼에 독립적이기 위해서 JVM을 이용한다. 자바 가상 머신이라고도 하는데 자바 바이트 코드를 실행할 수 있는 주체이다.

https://user-images.githubusercontent.com/32893340/59729700-95e52a80-927a-11e9-8a5c-bfdecbf3716a.png

JAVA 프로그램 동작 과정

  1. 프로그램이 실행되면 JVM은 OS로부터 이 프로그램이 필요로 하는 메모리를 할당받는다.
  2. 자바 컴파일러(javac)가 자바 소스 코드(.java)를 읽어들여 자바 바이트 코드(.class)로 컴파일한다.
  3. Class Loader가 동적 로딩(Dynamic Loading)을 통해 class 파일들을 로딩 및 링크하여 런타임 데이터 영역(Runtime Data Area), JVM의 메모리에 올린다.
  4. Execution Engine이 메모리에 올라간 class들을 기계어로 변경해 명령어 단위로 실행한다.
  5. 실행 과정 속에서 JVM은 상황에 따라 Thread Synchronization과 GC 같은 관리 작업을 수행한다.

https://user-images.githubusercontent.com/32893340/59734414-50315d80-928c-11e9-9a25-35cf29675d29.png

JVM 구성

Class Loader (클래스 로더)

클래스 로더는 실행을 위해 자바 바이트 코드를 로드하고 검증한다. 검증한 다음 자바 바이트 코드를 위해 메모리를 할당한다. 즉 RunTime 시점에 자바 바이트 코드들을 엮어서 RunTime Data Area로 적재하는 역할을 한다.

RunTime Data Areas

RunTime Data Areas 영역은 JVM 메모리를 나타낸다. 각각의 영역은 실행 중에 다른 용도로 사용된다.

  • PC Register : 현재 실행 중인 명령어의 주소를 가지고 있는 곳
  • Stack Area : 메소드 호출과 로컬 변수가 저장되는 메모리
  • Native Method Stack : JAVA 외의 언어로 작성된 네이티브 코드들을 위한 Stack
  • Heap : 프로그램 상에서 런타임시 동적으로 할당하여 사용하는 영역
  • Method Area : 클래스 이름, 부모 클래스 이름, 메소드 정보 및 모든 정적 변수 등의 바이트 코드를 저장하는 곳

모든 스레드는 고유한 PC Register, Stack , Native Method Stack을 가지고 있지만 모든 스레드는 Heap, Method Area는 공유한다.

Execution Engine

Class Loader에 의해 메모리에 로드된 자바 바이트 코드들을 기계어로 변경해 명령어 단위로 실행하는 역할을 한다. 엔진 내부에는 Interpreter, JIT Compiler, Garbage Collector가 있다. 이 중에서 기계어로 변경해주는 엔진은 Interpreter, JIT Compiler 2가지가 존재한다.

  1. Interpreter

    인터프리터 실행 엔진은 자바 바이트 코드를 명령어 단위로 읽어서 실행한다. 다른 인터프리터 언어와 동일하게 작동한다. 그래서 이 방식은 한 줄 씩 수행하기 때문에 느리다.

  2. JIT Compiler (Just In Time Compiler)

    적절한 바이트 코드를(자주 사용되는, 혹은 한번 사용 이후) 기계어로 변경해서 엔진이 기계어로 컴파일된 코드를 실행하도록 도와준다. 기계어로 다시 컴파일할 필요가 없음으로 속도가 매우 빠르다고 할 수 있다.

    최초 JVM이 나왔을 당시 Interpreter 방식이었기 때문에 속도가 느리다는 단점이 두각되었다. 하지만 JIT Compiler를 통해 속도에 대한 단점을 보완했다.. 그렇다고 해서 모든 코드를 JIT 컴파일러가 실행하는 것은 오버헤드를 야기 할 수 있다. JIT가 자바 바이트 코드를 기계어로 변환하는데 있어서 드는 비용이 매우 크기 때문이다. 그래서 처음엔 Interpreter 방식을 사용하다 일정 기준이 넘어가면 JIT Compiler로 미리 컴파일을 한다고 한다. 이러한 특징 때문에 가끔 자바 프로그램을 개발하다보면 같은 로직인데 최초 실행 시에 느리게 작동하는 것을 느낄 수 있다.

  1. Garbage Collector

    GC는 Heap 메모리 영역에 생성된 객체들 중 참조되지 않는 객체들을 탐색 후 제거하는 역할을 한다. 매우 편리한 기능이지만 GC만 믿고 작업한다면 성능 저하가 올 수 있다. GC에 대해 기술하려면 양이 매우 많기 때문에 나중에 따로 Heap 영역과 함께 정리하려고 한다.

profile
안드로이드 개발자

0개의 댓글