본문 바로가기
WhiteShip Study

1. JVM은 무엇이며 자바 코드는 어떻게 실행하는 것인가?

by 이석준석이 2020. 12. 5.

참고

howtodoinjava.com/java/basics/jdk-jre-jvm/

www.inflearn.com/course/the-java-code-manipulation/dashboard

 

더 자바, 코드를 조작하는 다양한 방법 - 인프런

여러분이 사용하고 있는 많은 자바 라이브러리와 프레임워크가 "어떻게" 이런 기능을 제공할 지 궁금한적 있으신가요? 이번 강좌를 통해 자바가 제공하는 다양한 코드 또는 객체를 조작하는 방

www.inflearn.com


0. 프로세스 설명

  1. Simple.Java 라는 자바 소스코드를 IDE (eclipse / intellij) 를 통해 작성한다.
  2. 해당 파일을 자바 컴파일러가 (javac) 컴파일하여 바이트코드로 만든다. (Simple.class)
  3. 해당 클래스 파일은 JVM 에 의해 실행된다.
  4. JVM은 바이트코드를 native Code(JVM이 실행할 수 있는 코드) 로 바꿔서 실행한다.

Java Execution Flow


간단한 과정을 수행해보자.

 

예시) HelloJava.java를 컴파일하고 실행해보자.

 

1. HelloJava.java

public class HelloJava {
    public static void main(String[] args) {
        System.out.println(".java 파일입니다.");
    }
}

 

2. javac 로 컴파일

javac HelloJava.java

 

3. HelloJava.class 확인

  • javap -c 를 사용하면 바이트코드를 잘 포맷된 모습으로 볼 수 있다. (실제로 열어서보면 아래와 같이 생기지 않았음)
javap -c HelloJava.class

결과
Compiled from "HelloJava.java"
public class HelloJava {
  public HelloJava();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: getstatic     #7                  // Field java/lang/System.out:Ljava/io/PrintStream;
       3: ldc           #13                 // String .java 파일입니다.
       5: invokevirtual #15                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
       8: return
}

 

4. 실행

  • java HelloJava

 

java 파일 실행 결과

 



1. JVM

  • 정의
    • Java 바이트코드(.class) 파일을 native 코드로 변환하여
    • 실행하는 것에 대한 표준이다.
  • native 코드로 변환하는 과정은
    • JIT (Just In Time) Compiler 혹은
    • Interceptor 가 제공한다.

아.. JVM은 native 코드를 실행해주는구나

  • 그렇다면 가장 먼저 뭘 해야할까? -> class file을 로딩해야지

JVM Arcitecture



1.1 Class Loader

  • class file을 로딩하는데 사용되는 시스템이 JVM 내부에 있는 Class Loader 이다.

3가지의 기능을 제공한다.

  1. Loading
    • .class 파일(바이트 코드) 을 읽어 "메소드" 영역에 저장한다.
    • JVM에는 3종류의 Loader가 있다. (BootStrap, extension and application class loader)
      1. 처음으로 BootStrap class loader 은 .class 파일을 찾으려고 한다. JRE의 lib 폴더안에 rt.jar 파일을 스캔한다.
        • rt.jar 파일은 모든 JRE의 라이브러리를 갖고있다.
      2. BootStrap이 찾지 못했다면 extension은 jre/lib/ext 폴더에서 class파일을 찾는다.
      3. extension도 찾지 못했다면, application classloader가 CLASSPATH environment로 주어진 곳에서 클래스파일을 찾는다.
      4. 여기서도 찾지 못했다면 ClassNotFoundException 이 던져진다.
  2. Linking
    1. classLoader에 의해서 로딩이 됐다면, bytecode verifier 가 바이트코드에 대한 검증을 한다.
    2. 문제없는 바이트코드라면, 클래스 파일에서 찾은
      1. static 변수
      2. static method를 메모리할당을 준비한다.
  3. Initializing
    1. 모든 static 변수들에 값이 할당되고, static block 이 수행된다.
      • // static 값들은 아래에 설명하게 될 Method Area에 저장된다.

로딩이 끝나면, 해당 클래스 타입의 객체 (Class<?>, ?.class)를 "Heap" 영역에 저장한다.

  • 따라서 우리는 ???.class 를 사용할 수 있는것이다.

 

메모리에 올린다라.. 근데 어디에 올리지?


1.2 JVM Memory Areas

  • JVM 내부에 메모리 영역은 여러 바트로 나뉘어있다.
영역 역할
Method Area 클래스 수준에 대한 정보가 저장된다.
- 패키지 정보가 포함된 클래스 이름 (ex) com.tistory.robin00q.MyClass
- 부모 클래스의 이름 (아무것도 상속받지 않은 클래스도 Object 클래스는 상속받는다.)
- 클래스 안에 있는 메소드
- 클래스 안에 있는 변수들
- 클래스 타입 (클래스인지, 인터페이스인지, Enum인지)

위에 명시한 클래스 수준에 대한 정보들은 Thread가 공유하는 자원이다.

Runtime Constant Pool
- 클래스 수준 정보에 대한 모든 레퍼런스(주소)를 저장한다.
- JVM은 런타임에 Constant Pool을 통해서 실제 메모리 주소를 찾아서 참조한다.
Heap 객체를 저장하는 영역이다.
- 위의 Method Area 에서 클래스에 대한 정보를 저장했다면, 실제 인스턴스들을 저장한다.

객체에 대한 정보 또한 Thread가 공유하는 자원이다.
Stack Thread 별로 독립적이다.

// Stack에 대한 설명은 너무 길어질 수 있기에 인터넷에서 찾아보시는게 TT
PC register Thread 별로 독립적이다.

- 만들어진 stack에 현재 어느 부분의 스택 프레임을 실행할 것인지를 가리키는 포인터이다.
- 해당 정보를 참조해 어떤 명령어를 수행할지 알 수 있다.
Native Method Stacks 자바는 많은 low level code 가 c, c++ 로 작성되었기 때문에, 해당 코드를 사용하기 위한 Stack이다.

다 할당했으면 이제 실행을 해보자


1.3 JVM Execution Engine

 

  • JVM에 할당된 코드들은 모두 execution engine 에 의해서 실행된다.
    • byte code를 machine code로 변경하고 실행한다.
  • 두가지 종류의 execution engine이 존재하며 아래와 같다.
    • Interpreter
      • 바이트코드를 하나씩 읽어서 실행하며, 최적화를 적용하지 않는다.
        • 한줄, 한줄 읽어서 machine code로 바꿔서 실행한다.
    • JIT Compiler
      • 실행 시점에서는 인터프리터 역할을 하며, 바이트코드를 machine 코드로 변경한다.
        • 실행 과정에서 코드를 캐싱하여, 추후에 다시 코드가 불리는 경우 재사용하여, 매번 machine 코드를 생성하는 것을 방지한다.

자바 바이트코드 ??

  • JVM 이 이해할 수 있는 언어로 변환된 Java 코드 (.class) 이다.

2. JRE

  • JRE(Java Runtime Environment)
    • 자바 어플리케이션을 실행하는데 목적이 있다.
      • 실행하기 위해서는 바이트 코드가 일단 필요하기에 JVM
      • 자바의 핵심 library를 사용하기 위한 Library들 (jars)
        • 자바 어플리케이션을 실행하기 위해 필요한 최소한의 Library들이다.

3. JDK

  • JRE + 개발에 필요한 툴을 제공한다.
    • developing
    • debugging
    • monitoring 등..

'WhiteShip Study' 카테고리의 다른 글

2. 자바 데이터 타입, 변수 그리고 배열  (0) 2020.12.11