본문 바로가기
Back-End/백기선님의 자바 스터디

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

by 7533ymh 2022. 3. 10.

목표

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

학습할 것

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

JVM이란 무엇인가

  • JVM - Java Virtual Machine
    • JAVA Byte Code를 운영체제에 맞게 해석해주는 역할 즉, 자바를 실행해주는 머신
    • 자바 어플리케이션을 클래스 로더를 통해 읽어 들여 자바 API와 함께 실행한다.
    • 자바와 OS사이에서 중개자 역할을 하며 자바로 작성된 모든 어플리케이션은 모두 JVM에서만 실행된다. ( 자바가 OS에 독립적인 이유 )
    • 하지만 JVM은 OS에 종속적이기 때문에 해당 OS에서 실행가능한 JVM이 필요하다.
    • 다른 어플리케이션 코드는 OS만 거치고 하드웨어로 전달된다.( OS에 종속적이다. )
    • JAVA 어플리케이션은 JVM을 한번 더 거치고, 하드웨어에 맞게 완전히 컴파일 된 상태가 아니고 실행 시에 interpret되기 때문에 속도가 느리다는 단점을 가지고 있다.
    • 요즘엔 바이트코드 ( 컴파일된 자바코드 )를 하드웨어의 기계어로 바꿔주는 JIT컴파일러와 향상된 최적화 기술이 적용되어서 속도의 격차가 많이 줄었다.
    • 내부의 GC(Garbage Collector)가 있어 사용되지 않는 메모리를 정리해 메모리 관리를 해준다.

컴파일 하는 방법

  • 소스코드.java 작성
  • javac.exe 즉, 자바 컴파일러를 통해 자바 소스코드를 바이트 코드로 컴파일한다. ( .class파일 생성 )

실행하는 방법

  • java.exe 즉, 자바 인터프리터를 통해 바이트 코드를 실행한다.
  • .class파일 실행
    • 내부적인 진행순서
      1. 프로그램의 실행에 필요한 클래스(.class파일)을 로드
      2. 클래스파일 검사 ( 파일형식, 악성코드 체크 )
      3. 지정된 클래스에서 main(String[] args) 호출
        • 하나의 자바 어플리케이션에는 main메서드를 포함한 클래스가 반드시 하나는 존재해야 한다!

바이트코드란 무엇인가

  • 자바 컴파일러에 의해 JVM이 이해할 수 있는 언어로 변환된 .class 파일
  • 자바 컴파일러에 의해 변환되는 코드의 명령어 크기가 1byte라서 바이트코드라고 불림

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

출처) https://beststar-1.tistory.com/3

  • 앞서 말한 것처럼 자바는 바이트코드로 한번 컴파일하는 과정과 바이트코드를 인터프리터 하는 방식 2가지로 진행된다. 고로, 속도가 느리다.
  • 이런 속도측면에서 해결하기 위해 나온 것이 JIT컴파일러이다.
  • JIT 컴파일러란?
    • Just In Time 컴파일러
    • 런타임시에 JVM에서만 돌아가는 자바 바이트 코드를 해당 플랫폼에 맞는 기계어 ( native code ) 로 컴파일해주는 특수한 컴파일러
  • 어떻게 동작하나?
    • 번역된 코드를 캐싱해둔 다음 똑같은 코드가 있다면 번역하지 읺고 캐싱해둔 값을 사용하여 매번 기계어 코드가 생성되는 것을 방지해 인터프리팅 시간을 단축시킨다.
    • JVM이 호출되는 메서드 각각에 대한 호출마다 호출 횟수를 누적해서 그 횟수가 특정 수치를 초과 할 때 컴파일하는 것
      • 횟수때문에 딱 한번만 실행될 경우 인터프리터 방식으로 실행
    • 인터프리터와 동시에 돌고 있다 ( 쓰레드 개념 )

JVM 구성 요소

출처) https://www.inflearn.com/course/the-java-code-manipulation/dashboard

  • JVM은 크게 4가지 구성요소로 이루어져 있다.
  1. 클래스 로더 시스템
    • 바이트코드를 읽어서 JVM의 실행 엔진이 사용할 수 있도록 Runtime Data Area ( 메모리 ) 에 적절히 배치하는 역할
    • 3가지 로딩 → 링크 → 초기화 순으로 진행된다.
      • 로딩
        • .class파일을 읽어서 바이너리 코드로 만들고 이를 메모리의 메소드 영역에 저장하는 과정
        • 저장하는 데이터는 다음과 같다.
          • Fully-Quailified Class Name(FQCN)
            • 클래스 로더, 클래스 패키지 경로, 패키지 이름, 클래스 이름을 모두 포함한 값
            • 예) java.lang.Character$Subset
          • Class, Interface, Enum을 구분하여 저장
          • 메소드와 변수
        • 로딩이 끝나면 해당 클래스 타입의 객체를 생성하여 메모리의 힙 영역에 저장한다.
        • BootStrap → Extension → Application Loader 순으로, 앞의 Loader가 로딩할 수 없으면 그 다음 Loader가 읽어내는 식
          • 개발자가 애플리케이션 구동을 위해 직접 작성한 대부분의 클래스는 애플리케이션 클래스로더에 의해 로딩된다.
      • 링크
        • 코드 내부의 래퍼런스를 연결하는 과정
        • Verify
          • .class 파일 형식이 유효한지 검사
        • Perpare
          • static변수와 기본 값에 필요한 메모리 준비
        • Resolve ( Optional )
          • 심볼릭 메모리 래퍼런스를 실제 메모리 래퍼런스로 교체
          • Optional인 이유는, 이 때 교체될 수 있고, 이후 사용이 일어날 때에 동적으로 교체될 수도 있기 때문이다.
      • 초기화
        • static변수를 초기화하고 값을 할당하는 과정
  2. 메모리( Runtime Data Areas )
    • 프로그램을 수행하기 위해 운영체제로부터 할당받는 메모리 영역
    • 힙 영역
      • 인스턴스화 된 모든 클래스 인스턴스와 배열,객체를 저장하며 모든 JVM 쓰레드에 공유되는 공유 자원
      • 여기서 인스턴스 변수 저장
      • GC에 있어서만 회수 가능
    • 메소드 영역
      • 클래스 수준의 정보 ( 클래스 이름, 부모 클래스 이름, 메소드, 변수 등 ) 저장
      • 여기서 클래스 변수 저장 ( static 변수, 일반 변수 등 )
      • 힙과 마찬가지 JVM 쓰레드에 공유되는 공유 자원
    • 스택 영역
      • 인스턴스 및 지역 변수의 참조 주소들을 저장
      • 쓰레드마다 런타임 스택을 만들고, 스택 프레임( 메소드 call ) 을 쌓는다.
      • 메소드 실행이 완료되거나 예외가 던져지면 스택에서 빠진다.
    • PC
      • 쓰레드마다 가지고 있는 Program Counter
      • 현재 실행할 부분을 가르키고 있다.
    • 네이티브 메소드 스택
      • 네이티브 메소드 호출할 때 사용하는 별도의 스택
      • 네이티브 메소드는 java가 아닌 c와 같은 언어로 구현된 메소드
  3. 실행 엔진
    • 인터프리터
      • 바이트코드를 한줄 한줄 읽어서 네이티브 코드로 변환
    • JIT 컴파일러
    • GC ( Garbage Collector )
      • 더 이상 참조되지 않는 객체를 모아서 메모리 정리

4-1. 네이티브 메소스 인터페이스 ( JNI )

  • 자바 애플리케이션에서 C, C++, 어셈블리로 작성된 네이티브 키워드를 사용한 함수를 사용할 수 있는 방법 제공

4-2. 네이티브 메소드 라이브러리

  • C, C++로 작성된 라이브러리

JDK와 JRE의 차이

출처) https://www.inflearn.com/course/the-java-code-manipulation/dashboard

  • JDK ( Java Development Kit )
    • 자바 개발 도구
    • JRE + 개발에 필요한 툴 ( javac.exe 등 )
  • JRE ( Java Runtime Environment )
    • 자바 실행 환경
    • 자바로 작성된 응용프로그램이 실행되기 위한 최소환경
    • JVM + 클래스 라이브러리 ( Java API )

javac 옵션

  • 11버전에서 컴파일한 바이트코드는 8버전에서 실행 불가능
  • 8버전에서 컴파일한 바이트코드는 11버전에서 실행 가능
  • 이를 방지하기 위해 컴파일러시 옵션을 줘서 낮은 버전에서도 실행 가능하게 할 수 있다.
  • javac
    • source: The version that your source code requires to compile.
    • target: The oldest JRE version you want to support.
    • javac(11버전) -source 1.8 -target 1.8 hello.java
      • 이런식으로 컴파일시 8버전으로도 실행가능

추가 학습

  • 컴파일러 , 인터프리터
    • 컴파일러 : 소스코드를 한꺼번에 컴퓨터가 읽을 수 있는 기계어로 변환
    • 인터프리터 : 소스코드를 빌드시에 아무것도 하지 않고 런타임시에 한줄 한줄 읽어가며 변환
  • javap.exe
    • 역어셈블러
    • class파일을 java파일로 만들어준다.

Reference

'Back-End > 백기선님의 자바 스터디' 카테고리의 다른 글

5주차 - 클래스  (0) 2022.03.20
4주차 - 제어문  (0) 2022.03.16
3주차 - 연산자  (0) 2022.03.10
2주차 - 자바 데이터 타입, 변수 그리고 배열  (0) 2022.03.10
백기선 자바 라이브 스터디  (0) 2022.03.10

댓글