DevCastleOne


※ 이 글에서 얻고자 하는것 : .java 파일이 실행되는 원리


1. JVM 이란?

2. 컴파일 하는 방법

3. 실행하는 방법

4. 바이트코드란?

5. JIT 컴파일러란 무엇이며 어떻게 동작

6. JVM 구성요소

7. JDK와 JRE





1. JVM 이란?


- Java Virtual Machine의 줄임말로써 bytecode를 실행시키는 주체 

- bytecode를 JVM이 각 OS에서 실행할수있도록 적절하게 기계어로 바꿔주는 중간 역할을 한다.

- JVM 자체는 표준이고 특정 벤더들이 JVM을 구현화 시킨다. ( 오라클 , 아마존 .... ) 



2. 컴파일 하는 방법


- .java 파일을 컴파일하면 .class 파일이 된다.

- JDK안의 Java\jdk1.8.0_251\bin안의 javac.exe 실행파일이 컴파일한다.



아래 사진은 하나는 .class 파일이고 그아래 사진은 .java 파일이다.



javac 명령어는 .java 파일을 .class 파일로 변환 시키는 작업을 하기도 하지만 변환 시키는 과정에서 옵션을 통해 다양함을 줄수있다.


명령어 : javac [options] [ sourcefile ] 


옵션1 : -classpath

: 컴파일러가 컴파일 하기 위해 필요한 라이브러리가 있는 경로를 지정해주는 옵션

: A.java 파일이 C:/java 디렉토리에 존재하고 필요한 라이브러리(클래스) 파일들이 C:/java/test에 존재한다면

 javac -classpath C:/java/test C:/java/A.java를 해주면 된다.



옵션2 : -target

: 지정된 자바버전의 VM에서 동작되어질수있도록 컴파일 시키는 옵션이다.

: 작성된 코드의 자바버전(JDK version) 과 실행시키려는 자바버전(JDK version)이 다를수 있는데 -target 옵션을 통해 해결할수있다.


1.1 , 1.2 , 1.3 .........................


1.1 : jvm 1.1 버전에서 호환되어질수 있는 클래스 생성




3. 실행하는 방법


xxx.class가 있다고 가정한다면 java xxx 명령어를 통해 실행 시킬수있다.



4. 바이트코드(ByteCode)란?


- .class 파일에 존재하는 Code

- 소스코드를 소프트웨어 인터프리터(Execution Engine)를 위해 저수준의 레벨로 컴파일된 프로그램 코드이다.

- 소스코드와 기계언어의 중간언어

- 어셈블리언어와 비슷하게 High level Language는 아니지만 기계언어와 달리 비교적 읽기 쉽다.

- 어셈블리언어는 CPU를 위해 만들어졌지만 바이트코드는 VM을 위해 만들어짐


5. JIT 컴파일러란? 어떻게 동작하는가?


자바파일이 실행되기 위해선 크게 2개의 과정이 사용된다.

소스코드를 바이트코드로 변환시키는 컴파일 과정과 바이트 코드를 실행시키는 인터프리터 과정이 있다.


- 컴파일러 : Runtime 이전에 소스코드를 기계어로 변환하는 작업방식

- 인터프리터 : 런타임 이후에 Row 단위로 해석을 하면서 프로그램을 작동시키는 방식


자바는 .class 파일을 메모리로 Load하고 실행하는 순간 인터프리터 방식으로 프로그램이 동작하기 때문에 기본적으로 Native 코드로 바로 실행하는것보다 느리게 된다. 

인터프리터 방식은 한줄씩 읽으면서 실행하게 되는데 읽을때 반복되는 코드가 존재할수 있게 된다. JIT컴파일러는 반복되는 코드를 모두 Native 코드로 변경해놓고 

반복되는 코드를 만났을때 Native 코드로 컴파일된 코드를 사용하게 한다. 이로인해 속도 개선이 될수있다.




6. JVM 구성요소


Class Loader , Runtime Data Areas , Execution Engine , JNI ( Java Native Interface ) 



- Class Loader



- 총 3가지 과정을 거침 ( 로딩 , 링크 , 초기화 순 )

-로딩 

  - .class안의 바이트코드를 읽고 메모리에 저장

  - 로딩계층구조로 이루어짐

     - BootStrap 클래스로더

         : JAVA_HOME/lib에 있는 코어 자바 API 제공. 최상위 우선순위를 가진 클래스 로더

     - Extension(Platform) 클래스로더

         : JAVA_HOME/lib/ext 폴더 또는 java.ext.dirs 시스템 변수에 해당하는 위치에 있는 클래스 읽음

     - Application 클래스 로더

   : 애플리케이션 클래스 패스(애플리케이션 실행할때 주는 -classpath 옵션 or java.class.path 환경변수의 값에 해당함)에서 클래스를 읽음 


   - .class 파일을 읽고 적절한 binary data를 만들고 메소드 영역에 저장

      BinaryData : 이진 파일이라고도 불리며 Text파일이 아닌 컴퓨터 파일로서 컴퓨터 저장과 처리목적으로 이진 형태로 인코딩된 데이터를 포함


   -메소드 영역에 저장하는 데이터

      - FQCN(Fully Qualified Class Name)

        : 클래스가 속한 패키지명을 모두 포함한 이름

      - 클래스 / 인터페이스 / 이넘

      - 메소드와 변수

   - 로딩이 끝나면 해당 클래스 타입의 Class 객체를 생성하여 "힙" 영역에 저장



-링크

   -  레퍼런스를 연결하는 과정

   -  Verify , Prepare , Resolve 과정이 있다.

       => Verify : .class 파일이 유효한지 체크

       => Prepare : 클래스 변수(static변수)와 기본값에 필요한 메모리 준비하는 과정

       => Resolve : 심볼릭 메모리 레퍼런스를 메소드 영역에 있는 실제 레퍼런스로 교체


- 초기화

   Static 변수의 값을 할당함 ( static 블럭이 있다면 이때 실행됨 ) 


  • Runtime Data Area


    • Method Area : 클래스,Method,변수,static 변수 , 상수 정보등이 저장되는 영역 ( 모든 Thread 공유)

    • Heap Area : new 명령어로 생성된 인스턴스와 객체가 저장되는 영역 ( 모든 Thread 공유 )

    • Stack Area : Method내에서 사용되는 값들(매개변수,지역변수,리턴값 등) 저장되는 구역으로 호출될때마다 하나씩 생성

    • PC Register : CPU의 Register의 역할과 비슷하다. 쓰레드 마다 쓰레드 내 현재 실행할 스택 프레임을 가리키는 포인터가 생성됨

    • Native Method Stack : 다른 언어(c,c++....)의 메소드 호출을 위해 할당되는 구역이다.


  • Execution Engine (실행엔진)
    • 인터프리터 , JIT 컴파일러 , GC로 이루어짐
      • 인터프리터 : 바이트코드 한줄씩 실행
      • JIT 컴파일러 : 인터프리터 효율을 높이기 위해 인터프리터가 반복되는 코드를 발견하면 JIT 컴파일러로 반복되는 코드를 모두 네이티브 코드로 변환. 다음부터 인터프리터는 Native로 변환된 코드를 사용함
      • GC :  더이상 참조되지 않는 객체를 해제한다.


  • JNI (Java Native Interface)
    • 자바 애플리케이션에서 c,c++,어셈블리로 작성된 함수를 사용할 수 있는 방법을 제공
    • Native 키워드를 사용한 메소드 호출
  • 네이티브 메소드 라이브러리
    • c,c++로 작성된 라이브러리


7.JDK와 JRE

- JRE ( JAVA RUNTIME ENVIRONMENT) : JVM + Library

  : ByteCode를 JVM으로 실행시키기 위한 파일들이 존재함.

  : (.class 파일을 해석해서 실행할수 있도록 해줌)

  : JAVA 프로그램을 실행시키는 환경 디렉토리

  : 실행만 시킬꺼면 JRE만 있으면 됨

  : jre/lib/rt.jar ⇒ java api 정보 존재


- JDK ( JAVA DEVELOPEMENT KIT ) => JRE + 개발 툴

  : Java 환경에서 돌아가는 프로그램을 개발하는 데 필요한 툴들을 모아놓은 소프트웨어 패키지입니다

  : javac.exe = 컴파일러. HelloWorld.java > HelloWorld.class

  : java.exe = 인터프리터. Byte code(HelloWorld.class)해석, 실행

  : javap.exe = 역어셈블러. HelloWorld.class > HelloWorld.java

  : javadoc.exe = 자동문서생성기. 소스 파일의 주석을 이용해 Java API 문서와 같은 형식의 문서를 자동으로 생성함

  : Java 환경에서 돌아가는 프로그램을 개발하는 데 필요한 툴들을 모아놓은 소프트웨어 패키지입니다




<참조>
-    백기선 온라인 강의
-    https://12bme.tistory.com/382
-    https://medium.com/@lazysoul/jvm-%EC%9D%B4%EB%9E%80-c142b01571f2 
-    https://pediaa.com/what-is-the-difference-between-interpreter-and-jit-compiler/#Interpreter
-    https://medium.com/@ahn428/java-jvm-java-virtual-machine-jre-java-runtime-environment-jdk-java-developement-kit-fed91def1d6f


'JAVA' 카테고리의 다른 글

자바 Dispatch란? ( static , dynamic , double Dispatch )  (0) 2020.12.25
자바 상속이란?  (0) 2020.12.25
[JAVA] 클래스란?  (0) 2020.12.16
Java13 switch 연산자  (0) 2020.11.28
JAVA] 자바 데이터 타입, 변수 그리고 배열  (0) 2020.11.21

이 글을 공유합시다

facebook twitter googleplus kakaoTalk kakaostory naver band