ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [live-study] 1: JVM은 무엇이며 자바 코드는 어떻게 실행하는 것인가.
    개발/Java 2020. 12. 23. 19:49

    백기선님이 진행하시는 live-study 1주차 과제
    1주차 과제

    목표

    자바 소스 파일(.java)을 JVM으로 실행하는 과정 이해하기.

    학습할 것

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

    JVM이란 무엇인가

    JVM(Java Virtual Machine) 은 하나의 추상 컴퓨팅 머신이라고 생각할 수 있다.

    컴퓨터 CPU안에 Instruction Set 이라고 하는 명령어 집합이 있는데, JVM에도 있다. 그리고 운영체제가 메모리를 관리하듯 JVM도 메모리를 관리한다.

    JVM이라는 추상 컴퓨팅 머신을 가짐으로써 얻는 이점이 무엇일까?

     

    만약 C언어로 작성한 파일이 윈도우에서 동작하더라도, 리눅스에서는 동작하지 않을 수 있다.

    같은 CPU를 사용하는 컴퓨터라도, 운영체제마다 커널이 다르기때문이라고 한다.

    즉, 프로그램 작성자가 사용자의 환경을 고려해야 한다.

     

    그러나 자바의 경우, 어느 환경이던 자바 컴파일러로 컴파일한 결과물인 .class 파일을 JVM 위에서 실행시킬 수 있다.

    프로그램 작성자가 사용자가 어떤 환경인지 고려하지 않아도 된다. 사용자가 자신의 환경에 맞는 JVM 구현체만 갖추고 있으면 된다.

    => 플랫폼 독립적이라고 한다.

     

    JVM은 자바 언어에 대한 정보를 가지지 않는다. 다만 바이너리 형식의 class 파일에 대해서만 알고있다.

    따라서 자바 뿐만이 아니라, 다양한 언어들이 JVM 기반에서 동작할 수 있다. (scala, kotlin ..)

     

     

    으로 자바로 작성된 프로그램 또는 자바 바이트 코드로 컴파일된 프로그램을 실행시켜주는 가상 머신이다. JVM을 이용하면 하나의 자바 코드(.java)로 한개의 목적 파일만을 생성해내고 각각의 다른 플랫폼/OS(Operating System)에서 프로그램을 실행할 수 있고 이 덕분에 두고 자바는 플랫폼에 독립적하다고 한다. 물론 각각의 환경에서 JRE를 설치해야하지만 한번만 설치하면 계속해서 사용할 수 있다. 그리고 이것을 Write Once Run Anywhere 라고 한다.

    덧붙이면 어셈블리어/기계어는 CPU마다 조금씩 달라지므로 환경에 맞는 코드를 작성해야한다.
    그리고 C언어의 경우 하나의 소스 파일만 가지고 각각의 OS에 맞는 컴파일러로 컴파일해서 여러개의 목적 파일이 생성된다.

     

    컴파일 하는 방법

    컴파일이란 작성한 코드를 컴퓨터가 이해할 수 있는 기계어로 바꿔주는 일을 말한다. .java파일을 컴파일 하기 위해서는 javac라는 자바 컴파일러를 이용해야 한다. (JDK를 설치하면 javac가 포함되어 있다.)

    javac [자바파일이름].java 

    커맨드를 실행하면 [자바파일이름].class이 생성된다. 이것을 자바 바이트 코드라고 부른다.

    실행하는 방법

    컴파일 후 생성된 자바 바이트 코드를 java로 실행시키면 된다. java명령어는 JRE안에 포함되어 있다. JRE는 JDK를 설치하면 포함되어 있다.

    java [자바파일이름].class

    위 커맨드로 실행시킬 수 있다.

    • javac 11버전으로 컴파일 한걸 하위버전에서 실행할 수 없다. 실행하게 하려면 javac의 target 옵션을 사용해야 한다.
    • 반대로 java8버전으로 컴파일하면 상위버전에서 실행할 수 있다.
    • IDE에서 컴파일은 항상 되고 있는 것이다. 잘못된 코드를 입력해서 빨간줄이 뜨는게 컴파일 에러.
    • IDE에서 실행은 Run을 누르면 실행이다.

    바이트코드란 무엇인가

    위에서 자바 파일을 컴파일 하면 생성되는 .class파일을 바이트코드라고 했는데, 바이트코드란 특정 하드웨어가 아닌 가상 환경에서 돌아가는 프로그램을 위한 이진 표현법이다. JVM 역시 가상 환경이기 때문에 자바 컴파일러가 바이트코드를 생성하고, JVM이 이 바이트코드를 실행시켜 결국 자바 프로그램이 동작하는 것이다.
    바이트코드는 기계어는 아니지만 가상 머신에 의해 기계어로 손쉽게 변환할 수 있는 코드이다.

    JIT 컴파일러란 무엇이고 어떻게 동작하는지

    컴퓨터 프로그램을 만드는 방법은 두 가지가 있는데 하나는 인터프리트 방식이고 다른 하나는 정적 컴파일이다.
    인터프리트 방식을 사용하는 언어는 대표적으로 파이썬이 있는데 프로그램을 실행 중 한줄씩 해당 기능에 대응하는 기계어로 번역하는 방식이다. 한줄씩 읽기 때문에 동일한 메소드를 실행시 같은 메소드를 반복해서 번역하는 비효율성이 있다.
    정적 컴파일은 프로그램을 실행하기 전에 기계어로 번역하는 방식이다. 실행전에 무조건 컴파일이 필요해서 여러 플랫폼에 맞게 컴파일을 하려면 시간이 오래 걸린다는 단점이 있다.
    JIT 컴파일러는 인터프리트 방식과 정적 컴파일을 섞은 방식이다.
    javac로 컴파일하는 것과는 전혀 관계가 없고, java로 프로그램을 실행할 때와 관련이 있다. line by line으로 인터프리터가 바이트코드를 기계어로 해석을 해서 실행한다. 그런데 반복되는 코드가 있다면 JIT컴파일러가 기계어로 변환해서 캐싱을 해놓고 재사용한다. (인터프리터와 JIT가 런타임에 동시에 실행된다. 그래서 Just-In-Time) 재해석할 필요없이 기계어가 바로 실행을 하니까 빨라진다. (캐싱위치는 JVM안에)

    JVM 구성요소

    Class Loader
    자바 컴파일러로 자바 파일을 컴파일하면 .class파일이 나온다고 했다. 클래스 로더는 클래스 파일들을 JVM내로 로드하는 모듈이다. 그리고 컴파일시점이 아닌 런타임에 동적으로 이 클래스들을 참조한다.

    Execution Engine
    클래스로더를 통해 배치된 클래스들을 실행시키는 역할을 한다.(클래스 파일 해석) JIT 컴파일러를 설명할때 나온 인터프리트 방식과 정적 컴파일 방식이 여기서 쓰인다.

    GC(Garbage Collector)
    GC는 메모리 관리를 한다. 동적으로 할당된 메모리가 사용되지 않으면 반환한다. 이를 통해 개발자는 비즈니스 로직에만 집중할 수 있다.

    Runtime Data Area (JVM 메모리 구조)
    JVM이 프로그램을 실행하기 위해 할당받은 메모리 영역으로 크게 5가지로 나뉜다.

    • PC Registers
      쓰레드가 생성될 때 마다 생기는 공간으로 어떠한 명령을 실행하게 될지에 대해 저장하는 메모리 공간이다.
      C언어는 연산을 수행하기 위해 값을 레지스터에 이동시키고 그 값을 변수 메모리 공간에 이동시키는 방법을 사용한다. 이 방식은 CPU마다 어셈블리어가 조금씩 다르므로 플랫폼 독립적일 수 없다.
      그래서 JVM은 Stacks-Base 방식으로 작동 하는데 CPU에 직접 Instruction을 수행하지 않고, Stack에서 Operand를 뽑아내 이를 별도의 메모리 공간에 저장하는 방식을 사용한다.
    • Method Area
      사용되는 클래스파일을 읽어서 변수, 반환형, 인자 정보 등등의 정보를 가지고 있다. new를 통해 생성되는 객체가 이곳에 저장되며 GC의 주 처리 영역중 하나다.
    • Heap
      사용자가 생성하는 객체의 인스턴스가 이곳에 할당된다. GC가 주로 처리하는 영역이다.
    • JVM Stacks
      쓰레드 제어를 위해 사용되는 영역이다. 쓰레드당 하나씩 갖는 영역이고, 쓰레드가 메소드를 호출하면 메소드 정보가 스택에 쌓이게 된다. 메소드의 매개변수, 지역변수, 임시변수, 돌아갈 주소 등을 저장하고 메소드 종료시 메모리 공간도 사라진다.
    • Native Method Stacks
      자바 이외의 언어로 작성된 코드를 위한 스택이다. JNI(Java Native Interface)를 통해 호출한다.

    JDK와 JRE의 차이

    JDK(Java Development Kit)은 자바로 개발을 하기위한 도구이다.
    JRE(Java Runtime Environment)는 자바 프로그램을 실행할 수 있는 환경을 제공하기 위한 도구이다.
    JDK는 JRE를 포함하고 있어서 JDK를 설치했다면 JRE를 설치하지 않아도 된다.

    댓글

Designed by Tistory.