ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 1주차 과제: JVM은 무엇이며 자바 코드는 어떻게 실행하는 것인가.
    Programming/Java live study 2020. 12. 24. 02:08
     

    whiteship/live-study

    온라인 스터디. Contribute to whiteship/live-study development by creating an account on GitHub.

    github.com

    목표

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

    학습할 것

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

    1. JVM이란 무엇인가

    Java Virtual Machine의 줄임말이며 Java 바이트코드를 OS에 맞게 해석해주는 역할
    어느 OS던지 Java 프로그램이 실행할 수 있도록 도와준다.

    바이너리코드

     - 0과 1로 구성되어 있고 컴퓨터가 이해할 수 있다.

     - C언어를 예시로 들면, .c를 컴파일 하면 .obj 파일이 생긴다. 여기서 .obj가 바이너리코드이다. 컴파일이 끝나면 링커로 여러 코드와 데이터를 연결하여 메모리에 실행 가능한 파일로 만든다. 이러한 과정이 모두 진행되어야 컴퓨터가 이해 할 수 있는 기계어로 구성된 실행 파일이 만들어진다.

     

    바이트코드

     - 0과 1로 구성되어 있는 이진코드이지만 가상머신이 이해할 수 있는 코드이다.

     - 고급 언어와 기계어 사이에 위치한다.

     - 기계어로 만들기 위해서는 인터프리터의 도움이 필요하다.

     

     Java 컴파일러는 .java파일을 .class라는 Java 바이트코드로 변환 시켜준다. 바이트코드는 기계어가 아니기 때문에 OS에서 바로 실행되지 않는다. 이때 JVM은 OS가 바이트코드를 이해할 수 있도록 해석해준다.

     

     JVM과 같이 중간 언어를 해석해주는 가상의 장치가 없으면, 운영체제가 바뀔 때 마다 그에 맞게 실행 가능한 프로그램으로 만들어야 한다. 하지만 Java의 JVM은 바이트코드를 기계어로 번역하기 때문에 운영체제에 JVM만 설치되어 있다면 어디서든 바이트코드를 기계어(바이너리 코드)로 바꿀 수 있다.

     

     Java뿐만 아니라 JVM 기반으로 동작하는 프로그래밍 언어는 다양한다. 대표적인 예로 클로저, 그루비, Kotlin 등이 있다.

     

    출처https://sowhat4.tistory.com/61 [Humbly]


    2. 컴파일 하는 방법

    java에서 컴파일 이란?
    java 언어로된 코드를 JVM이 인식할 수 있는 바이트코드로 변환하는 것을 의미

    Java를 빌드하게 되면 자바 컴파일러가 .java 파일을 JVM이 이해할 수 있는 바이트코드인 .class 파일로 바꿔준다.

    Class Loader를 통하여 바이트코드를 JVM내로 로드하고 Execution Engine에서 두 가지 방식을 활용(interpreter, JIT)하여 기계어로 바꿔준다.

     

    컴파일 과정

    public class Main(
        public static void main(String[] args) {
            System.out.println("hello world");
        }
    )

     

    $ javac Main.java

     

    컴파일된 .class 파일

     

    // class version 55.0 (55)
    // access flags 0x21
    public class me/hyeonic/week01/Main {
    
      // compiled from: Main.java
    
      // access flags 0x1
      public <init>()V
       L0
        LINENUMBER 3 L0
        ALOAD 0
        INVOKESPECIAL java/lang/Object.<init> ()V
        RETURN
       L1
        LOCALVARIABLE this Lme/hyeonic/week01/Main; L0 L1 0
        MAXSTACK = 1
        MAXLOCALS = 1
    
      // access flags 0x9
      public static main([Ljava/lang/String;)V
       L0
        LINENUMBER 6 L0
        GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
        LDC "Hello World"
        INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V
       L1
        LINENUMBER 7 L1
        RETURN
       L2
        LOCALVARIABLE args [Ljava/lang/String; L0 L2 0
        MAXSTACK = 2
        MAXLOCALS = 1
    }

     

     인텔리제이의 show Bytecode를 활용하여 Main.class의 바이트코드를 쉽게 볼 수 있다. shell에서 실행 시 javap -c 명령어로 해석된 바이트코드를 볼 수 있다.

     

     참고로 인텔리제이나 이클립스에서 코드를 작성하는 것 자체가 컴파일이 진행 중인 것을 알 수 있다. 그렇기 때문에 컴파일시점에 생기는 컴파일 에러는 코드를 작성하는 행위 만으로도 확인 할 수 있다.

    추가 과제 javac 옵션 정리

     -d: class file이 생성될 부분을 결정한다.

     -sourcepath: 인터페이스의 정의나 클래스의 정의를 찾기 위해 소스코드의 경로를 지정할 수 있다. 

     -classpath or -cp: 컴파일할 때 필요한 class 파일의 경로를 지정한다.

     -encoding: 소스파일에 사용된 인코딩을 지정한다.

     -g: 디버깅 정보를 출력한다.

     -verbose: 컴파일러가 진행한느 작업을 모두 출력한다.

     -source: 소스파일 자바 버전 지정

     

    출처:

    www.notion.so/1-01b08b753f0c4e93b16a96101c75d382

    gblee1987.tistory.com/173


    3. 실행하는 방법

    $ java Main

     

     그 밖에도 IDE (통합 개발 환경)에 따라서 실행하는 방법이 다르다.


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

    바이트코드는 특정 하드웨어가 아닌 가상 컴퓨터에서 돌아가는 실행 프로그램을 위한 이진 표현법이다. 하드웨어가 아닌 소프트웨어에 의하여 처리되기 때문에 기계어 보다 추상적이다.

     - Java에서 바이트코드는 Java 가상 머신인 JVM이 이해할 수 있는 언어로 변환된 Java 소스코드를 의미한다. Java에서 바이트코드로 표현된 파일의 확장자는 .class 이다. 

     - 바이트코드의 이름이 붙은 이유는 변환된 코드의 명령어 크기가 1byte이기 때문이다. 


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

     Java에서 기존 클래스 파일인 바이트코드를 실행하는 방법은 interpreter 방식이다. interpreter는 명령어를 하나씩 해석하여 처리하기 때문에 명령어를 하나씩 실행하는 속도는 빠를지 모르지만 전체적인 코드를 생각하면 실행 속도가 느린 것을 알 수 있다.

     

     이를 해결하기 위해 JIT 컴파일러가 등장하였다.

     

    JIT (Just-in-time) 컴파일러란?
    Just-In-Time 컴파일 방식을 활용. 프로그램을 실제 실행하는 시점(런타입 시점)에 기계어로 번역하는 컴파일 기법을 활용한 컴파일러

     JIT 컴파일러는 자주 사용하는 코드를 캐싱하고 이후에 같은 코드가 나오면 캐싱된 것을 가져다 쓴다. 매번 기계어로 번역하는 interpreter 방식보다 빠르게 기계어로 번역할 수 있다.

     

     JIT 컴파일러는 런타입 시에 동작한다. interpreter와 함께 Thread로 동시에 동작한다.

     

     단점은 초기 구동할 때 런타임 단계에서 컴파일하는데 시간과 메모리를 소모한다. 정적 컴파일된 프로그램에 비해 실행속도가 느리다.


    6. JVM 구성요소

    JVM의 구조

    JVM

    6.1 Class Loader

     - .class에서 바이트코드를 읽고 메모리에 저장한다.

     - class loading에는 Loading, Linking, initialzing 단계로 나뉜다.

     

    단계 설명
    loading class를 읽어오는 과정
    linking 레퍼런스를 연결하는 과정
    initialzation static 값 초기화 및 변수에 할당

    6.2 memory

     - Java 프로그램이 실행될 때 JVM이 실행되면서 OS로 부터 할당받는 메모리.

     

    공간 설명
    Stack 메소드가 호출되면 할당된다. LIFO 구조이고, 스레드가 생성되면 각 스레드마다 하나의 stack segment를 가진다. 메소드 수행시 발생되는 지역변수 또한 저장된다. stack에서는 heap 영역의 객체를 참조할 수 있으며, 기본타입 변수는 stack에 직접 생성된다.
    Heap Java 프로그램이 실행되면서 동적으로 생성된 객체가 저장되는 공간
    PC Register 현재 수행중인 JVM 명령 주소를 가진다. CPU안에 Program Counter와 비슷한 역할을 한다.
    Native Method Stack Java 이외의 언어로 된 코드들을 위한 stack이다. JIN을 통하여 다른 언어의 코드를 수행한다.
    Method class의 구성요소인 static 변수, 생성자, 메소드, 멤버변수들이 저장된다.

    6.3 Excution Engine

    엔진 설명
    interpreter 바이트코드를 한줄씩 실행한다.
    JIT 컴파일러 interpreter의 효율을 높이기 위해 반복되는 코드를 캐싱하고, 컴파일된 코드를 바로 사용한다.
    Garbage Collector 더 이상 참조하지 않는 객체들을 정리한다.

    6.4 JNI

     - Java Native Interface

     - Java 애플리케이션에서 OS가 구현된 언어(C, c++, 어셈블리어)로 만들어진 함수들을 사용할 수 있는 방법을 제공한다.

    6.5 Native method Libraries

     - C, C++등으로 작성된 라이브러리


    7. JDK와 JRE의 차이

    7.1 JRE

     - Java Runtime Enviroment

     - JVM + 라이브러리

     - JVM의 실행환경을 구현

    7.2 JDK

     - Java Development Kit

     - JRE + 개발시 필요한 도구(javac, java 등)


    8. 라이브 중 정리한 내용

    바이트 코드 X 바이트코드 O

     - 바이트코드가 맞는 표현이다.

     

    컴파일타임 vs 런타임

    타임 설명
    컴파일타임 개발자가 소스코드를 작성하고 컴파일을 통해 실행 가능한 프로그램이 되는 과정을 의미한다.
    런타임 컴파일 과정을 마친 애플리케이션이 사용자에 의해서 실행되는 시점을 의미한다.

    [참고] bash에서 javac를 실행하는 부분이 컴파일타임이고, 인텔리제이나 이클립스같은 idea에서는 소스코드를 작성하는 중에도 상시로 컴파일이 되고 있다.

    'Programming > Java live study' 카테고리의 다른 글

    6주차 과제: 상속  (0) 2020.12.24
    5주차 과제: 클래스  (0) 2020.12.24
    4주차 과제: 제어문  (0) 2020.12.24
    3주차 과제: 연산자  (0) 2020.12.24
    2주차 과제: 자바 데이터 타입, 변수 그리고 배열  (0) 2020.12.24

    댓글

Designed by Tistory.