본문 바로가기

Java

[WS live-study ] 1주차:JVM은 무엇이며 자바 코드는 어떻게 실행하는 것인가

JVM이란 무엇인가

  • JAVA Virtual Machine(자바 가상 기계)의 약자
  • 실행 전 JAVA 어플리케이션을 운영체제로 바로 전달되는 것이 아니라 JVM을 거쳐서 실행되기 때문에 특정 환경에 구애받지 않는다. (Write once, run anywhere : 한번 작성하면 어디에서나 실행된다. 가 가능하게 된것.)
  • 메모리 관리를 알아서 해준다. (JVM에 Garbage Collector가 포함되어 있다.)
  • 스택기반의 가상머신이다.

 

1. 컴파일을 하는 방법

1) 자바 코드를 작성한 후 확장자가 .java인 파일을 만든다.

 

2) 콘솔화면에서 javac '파일이름명.java'를 작성 후 엔터를 누르면 컴파일이 된다. 바이트 파일(.class)가 생긴 것을 확인할 수 있다.

여기서 JAVAC란 '자바 컴파일러'를 의미하고, 자바 컴파일러는 JVM이 이해할 수 있는 소스 코드(바이트코드)로 변환한다.

자바 컴파일러는 자바를 설치할 때 javac.exe로 같이 설치된다.

 

javac 위치

 

2. 바이트코드란 무엇인가

확장자가 .class이다. 우리가 작성한 java 코드를 JVM이 이해할 수 있는 언어로 변환된 중간 코드이다.

JVM은 변환된 바이트코드를 각각의 운영체제에 맞게 기계어로 다시 컴파일하여 실행한다.따라서 바이트코드는 가상머신이 설치되어 있다면 어느 환경에서든 실행가능하다.

 

 

 

3. 실행하는 방법

첫번째 방법) 콘솔에서 java '파일명' 을 작성 후 엔터를 누르면 실행된다.

두번째 방법) IDEA를 이용하여 실행하면 됨 (링크- intellij 에서 java프로젝트 생성부터 실행까지 하기)

 

 

 

4. JVM의 구성요소

런타임: 컴퓨터가 실행되고 있는 동안의 동작. 

 

 

Class Loader

바이트코드를 런타임 데이터 영역에 배치시키는 역할을 한다. 시작 바이트코드에서 다른 클래스 파일의 메서드를 호출할 경우 해당 클래스 파일이 있는지 찾아 (JRE 라이브러리 또는 CLASSPATH 환경변수에 지정된 폴더 등) 해당 바이트코드가 올바른지 확인하고 메서드 영역에 배치한다.

이렇게 클래스 파일들이 로딩되면 JVM이 종료할 때까지 유지된다.

 

Execute Engine

메모리에 로드된 클래스를 기계어로 변형하여 실행하는 역할을 한다. 자바 컴파일러가 바이트코드로 변환은 했지만 이 소스는 사람이 이해하기 쉬운 고급언어로 구성되어 있기 때문에 기계어로 변환한다. heap 메모리 영역에 생성된 객체 중 Garbage Collector가 사용하지 않은 메모리를 찾아 삭제하여 메모리 관리를 해준다.

여기서는 바이트코드를 한줄씩 읽어 실행하는 인터프리트 방식과 JIT 컴파일 방식으로 두가지 방식이 있다. 

 

Runtime Data Area

OS에서 해당 프로세스에게 할당해주는 메모리를 JVM은 용도에 맞게 분할하여 사용한다.

 

PC Register

Thread가 어떤 명령어로 실행할지에 대한 것을 기록하는 영역으로 현재 수행 중인 JVM 명령의 주소를 갖는다.

 

JVM  Stack

프로그램 실행과정에서 임시로 생성되었다가 소멸되는 데이터를 저장하는 영역이다. 이 영역에 저장되는 데이터의 예로는 메소드의 매개변수, 리턴 값,  지역변수, 연산 중 발생하는 임시데이터 등이 있다.

 

Native Method Stack

자바 외 언어로 작성된 네이티브 코드를 위한 영역이다. 

 

Heap Area

동적인 데이터 영역으로 객체와 배열이 여기에 저장된다. 물론 Method Area에 올라온 클래스들만 객체 생성이 가능하다. Heap에 할당된 데이터는 Garbage Collector의 대상이 된다.

 

Method Area (Class Area)

모든 스레드가 공유하는 영역으로 JVM이 시작될 때 생성된다. 클래스가 올라갈 때 초기화 데이터(상수 자료형, 클래스 변수 등)가 여기에 저장된다.

 

 

5. JIT 컴파일러

인터프리터는 한줄한줄 실행하기 때문에 인터프리터의 단점인 속도가 느리다는 점을 가지고 있다. 이를 보완한 것이 JIT이다.

JIT는 인터프리트와 컴파일의 두가지 방식을 혼합한 방식이라고 할 수 있는데, 인터프리터가 차례로 실행하면서 기계어 코드를 생성하면 그 코드를 캐싱하여, 같은 함수가 여러번 호출이 될 경우 같은 기계어 코드를 생성하는 것을 방지하고 캐싱되어 있는 기계어 코드를 사용하는 방식이다. 

 

출처 : https://aboullaite.me/understanding-jit-compiler-just-in-time-compiler/

JVM은 인터프리터를 사용하다가 사용해야할 때 "적시에" JIT compiler 방식으로 한다. JIT 컴파일러는 런타임에 바이트코드를 기계어로 컴파일 하여 Java 프로그램의 성능을 향상시킨다. 메소드가 컴파일되면 JVM은 해석하는 대신 해당 메소드의 컴파일된 코드를 직접호출한다.

 

 

6. JDK와 JRE의 차이

JRE(Java Runtime Environment 자바 개발 환경)

목적: 자바 프로그램 실행

컴파일된 자바 프로그램을 실행시키기 위한 도구가 포함되어 있다.

 

JDK (Java Development Kit 자바 개발 도구)

목적: 자바 개발 + 자바 프로그램 실행

JRE + 자바를 프로그래밍하기 위한 도구가 포함되어 있다.

 

 

 

 

 

 


정리하는데 참고했던 곳