Monday

1주차 : JVM과 자바 코드 실행 원리 본문

언어/Java 기타

1주차 : JVM과 자바 코드 실행 원리

뉴비2 2021. 2. 9. 21:43

* 개인적인 공부 글로 틀린 정보가 있을 수 있습니다. 만약 있다면 거침없이 댓글로 알려주시면 감사하겠습니다.


목차

  • JVM이란 무엇인가
  • 컴파일 하는 방법
  • 실행하는 방법
  • 바이트코드란 무엇인가
  • JIT 컴파일러란 무엇이며 어떻게 동작하는지
  • JVM 구성 요소
  • JDK와 JRE의 차이

1. JVM 이란?

JVM이란 Java Virtual Machine으로 자바의 바이트 코드를 해석하는 기계 즉, 자바 실행을 도와주는 프로그램을 말한다.

컴퓨터는 본래 0과 1만 이해한다. 하지만, 우리는 프로그래밍 언어로 프로그램을 작성해도 정상적으로 실행이 된다. 그 이유는 중간에 컴퓨터가 이해할 수 있게 0과 1로 번역해주는 무엇인가가 있기 때문이다. 정확히 말하자면 기계어로 번역되어야 컴퓨터가 이해한다. 운영체제마다 기계어는 달라 같은 언어의 같은 코드라도 운영체제에 따라 실행되지 않을 수 있다. 하지만, 자바는 JVM이 중간에서 해석 역할을 해주어서 우리는 JVM이 알아듣게 자바 코드만 작성하면 JVM이 알아서 운영체제에 맞게 기계어로 번역해준다. 즉, 우리는 JVM 덕에 운영체제를 신경쓰지 않고 똑같은 자바 코드를 작성할 수 있게됐다.

 

2. 컴파일 하는 방법

컴파일이란 .java 파일을 .class 파일(바이트 코드)를 만드는 것으로 JVM이 알아들을 수 있는 번역작 업을 하는 것이다. 보통 Eclipse, Intellij 같은 IDE 도구를 쓰면 Run 버튼을 한 번 클릭하는 것으로 컴파일 후 빌드, 실행이 자동으로 된다. 하지만 이는 Javac라는 자바 컴파일러를 통해 컴파일이 된 결과이다.

3. 실행하는 방법

실행하는 방법 또한, 우리는 보통 IDE를 통해서 Run 버튼을 클릭하는 것으로 해결할 수 있다. 하지만, 이것 또한 java.exe를 통해 프로그램을 실행한 결과다. "Java 클래스파일이름" 을 CMD 창에 치면 Java 파일을 실행할 수 있다.

 

4. 바이트코드란 무엇인가?

바이트 코드란 JVM이 이해할 수 있는 코드다. 컴퓨터에서 실제로 일을 하는 애는 CPU다. 위에서 말했지만 우리가 영어로 프로그램 작성해도 프로그램을 실행할 수 있는 이유는 중간에 번역하는 누군가가 있기 때문이다. 자바에서는 JVM이란 놈이 중간에서 번역 역할을 한다. 즉, 우리는 JVM이 알아들을 수 있게만 해주면 JVM이 알아서 운영체제가 알아듣게 번역해서 넘겨주고 CPU가 이를 실행한다.

자바는 .Java -> .Class -> JVM이 실행 이 순서로 프로그램을 실행한다.

 

5. JIT 컴파일러란?

JIT 컴파일러의 Just-In-Time 컴파일러의 약자이다. 자바는 운영체제가 바로 알아들을 수 있게 코드를 번역시키지 않고 JVM을 통해 번역과정이 이루어지기에 매번 프로그램을 실행할 때마다 JVM이 코드 한줄 한줄 씩 번역 해주어야한다.(이를 인터프리터 방식이라 한다.) 그래서, 프로그램이 실행할 때 마다 C언어와 같은 컴파일러 방식에 비해 속도가 조금 느리다. 이런 단점을 보완하기 위해, JIT 컴파일러는 반복적으로 번역해야하는 코드들을 캐싱(특정 공간에 저장)해두었다가 이를 사용한다. 따라서, JIT 컴파일러 때문에 컴파일 할 때 속도가 향상될 수 있다.

 

 

6. JVM 구성 요소

 

출처 : https://dzone.com/articles/jvm-architecture-explained

JVM는 크게 4가지 구성요소로 이루어져있다.

 

1) 클래스 로더(Class Loader)

바이트 코드(.class)를 실행할 때 클래스 객체를 메모리에 생성하는 역할을 한다.

 

2) Runtime Data Area

  • Method Area - 클래스와 인터페이스의 메타데이터가 저장된다. 메소드 코드, 생성자 정보 등이 저장되며 모든 Thread에 의해 공유되는 영역이다. 또한, Method Area는 내부에 클래스/인터페이스의 메소드, 필드, 문자열 상수 등의 레퍼런스가 저장되는 Runtime Constant Pool 영역이 있다.
  • Heap Area - new 연산자 등으로 생성된 인스턴스와 배열 등이 저장되는 영역이다. GC가 발생되는 영역이다.
  • Stack - 메소드 데이터(지역변수, 메소드 파라미터 등)을 저장하기 위한 영역이다. Thread 로 공간이 할당되며 메소드 진입시마다 메소드 데이터를 포함하는 Stack Frame이 생성되었다가 종료시 사라진다.
  • PC Register - 각 Thread 마다 할당되는 영역이며 Thread가 실행할 JVM 명령의 주소를 저장한다.
  • Native Method Area - Java 외의 언어로 작성된 코드(Native Code, JNI로 실행되는 코드)를 위한 Stack 영역이다. 쓰레드에서 네이티브 방식의 메소드를 실행할 경우 Native Method Stack에 쌓는다.

3) Execution Engine

클래스 로더를 통해 배치된 클래스 파일(바이트 코드)를 실행 가능하도록 해석(인터프리터 or JIT)하는 역할을 한다. 

 

4) Garbage Collection

Runtime Data Area의 Heap 영역 대상으로 참조되지 않은 오래된 변수들을 찾아 제거하고 메모리를 확보하는 역할을 한다.

7. JDK와 JRE의 차이 

출처 : https://o7planning.org/11911/configuring-eclipse-to-use-the-jdk-instead-of-jre

 

JRE는 Java Runtime Environment의 약자로 자바 프로그램 실행에 필요한 최소한의 구성 요소들이 포함되어 있다. JDK는 Java Development Kit의 약자로 자바 컴파일러, 자바코드를 C++ 에서 사용하게 해주는 javah와 같은 자바 개발 도구들이 포함되어 있다.

Comments