[JAVA] JVM

handa·2023년 2월 20일
0
post-thumbnail

JVM은 무엇이며 자바 코드는 어떻게 실행하는 것인가
음... Java Virtual Machine... 서버가 자바 코드를 읽을 수 있게 변환...? 모름...

1. JVM (Java Virtual Machine)

자바를 실행하기 위한 가상 기계(컴퓨터)
Java는 OS에 종속적이지 않다는 특징을 가지고 있다. OS에 종속받지 않고 실행되기 위해선 OS 위에서 Java를 실행시킬 무언가가 필요하다. 그게 바로 JVM이다.
즉, OS에 종속받지 않고 CPU가 Java를 인식, 실행할 수 있게 하는 가상 컴퓨터이다.

Java 소스코드, 즉 원시코드(.java)는 CPU가 인식을 하지 못하므로 기계어로 컴파일을 해줘야한다.
하지만 Java는 이 JVM 이라는 가상머신을 거쳐서 OS에 도달하기 때문에 OS가 인식할 수 있는 기계어로 바로 컴파일 되는게 아니라 JVM이 인식할 수 있는 Java bytecode(
.class)로 변환된다.
컴파일된 파일을 OS에 종속받지 않고 CPU가 인식할 수 있도록 처리해주는 것이 JVM이다.

Java compiler 가 .java 파일을 .class라는 Java bytecode로 변환한다.
Java compiler는 JDK를 설치하면 bin에 존재하는 javac.exe를 말한다. (즉, JDK에 Java compiler가 포함)
javac 명령어를 통해 .java를 .class로 컴파일

변환된 bytecode는 기계어가 아니기 때문에 OS에서 바로 실행되지 않는다.
이 때, JVM이 OS가 Java bytecode를 이해할 수 있도록 해석해준다.
JVM이 OS가 Java bytecode를 이해할 수 있도록 해석해주기 때문에 Java는 어떠한 OS에도 종속적이지 않다는 것이다

2. 컴파일

Java Compiler에 의해 JVM이 인식할 수 있는 Java bytecode(*.class)로 변환
Java Compiler는 JDK를 설치하면 javac.exe라는 실행 파일 형태로 설치된다.

vi HelloWorld.java
class HelloWorld {
	public static void main(String[] args) {
    	System.out.println("HelloWorld!!");
    }
}
javac HelloWorld.java

HelloWorld.java를 컴파일 하여 HelloWorld.class이 생성된다.

3. 실행

java 명령어로 .class 파일을 실행 시킬 수 있다.
JDK 디렉토리의 /bin 폴더에 존재하는 java.exe는 JVM을 구동시키기 위한 명령 프로그램(JRE)
설정된 classpath에 파일이 있어야 구동가능
리눅스 /etc/profile 에서 classpath 확인가능

cd /classpath
java HelloWorld
HelloWorld!!       <-- 출력되면 실행 성공

4. 바이트코드

가상 컴퓨터(VM)에서 돌아가는 실행 프로그램을 위한 이진 표현법

자바 바이트 코드(Java bytecode)는 JVM이 인식할 수 있게 변환된 자바 소스코드
명령어 크기가 1바이트라서 자바 바이트 코드

바이트 코드는 다시 실시간 번역기 또는 JIT 컴파일러에 의해 바이너리 코드로 변환

바이너리 코드(이진코드)

컴퓨터가 인식할 수 있는 0과 1로 구성된 이진코드

기계어

0과 1로 이루어진 바이너리 코드
기계어가 이진코드로 이루어졌을 뿐 모든 이진코드가 기계어인 것은 아니다.
기계어는 특정한 언어가 아니라 CPU가 이해하는 명령어 집합, 제조사마다 기계어가 다를 수 있다.

CPU가 이해하는 언어는 바이너리 코드, 가상 머신(JVM)이 이해하는 코드는 바이트 코드
바이트코드(Java bytecode) -> JVM -> 바이너리 코드 -> CPU

5. JIT 컴파일러

JIT 컴파일(just-in-time compliation) 또는 동적 번역(dynamic translation) 이라고 한다.
JVM에서 바이트 코드를 CPU가 인식할 수 있도록 기계어로 변환하는 단계를 거치는데 이때 JVM에서 바이트 코드들을 기계어로 번역하는 컴파일러가 JIT 컴파일러이다.

JVM은 총 2가지 변환을 수행한다.
- Java, kotlin 파일을 바이트 코드로 변환하는 과정
- 바이트 코드를 기계어로 변환하는 과정

JIT 컴파일러는 기계어로 변환된 코드를 캐시에 저장시켜 재사용시 컴파일을 다시 하지 않아도 된다.
즉, 런타임에 바이트코드를 기계어로 변환하는 컴파일을 하면서 이미 캐시에 있는 기계어로 다시 변환하지 않고 사용한다.

6. JVM 구성요소

6-1. 클래스 로더 (Class Loader)

바이트 코드를 읽어오며 메모리에 적절히 배치하는 역할

  • 로딩 (Loading): .class파일을 읽어옴

  • 링크 (Linking): 코드 내부의 래퍼런스를 연결함

  • 초기화 (Initialization): 클래스에 있는 static 값들을 초기화 함

6-2. 실행 엔진 (Execution Engine)

클래스를 실행시키는 역할

  • 인터프리터 (Interpreter): 바이트 코드를 한줄씩 읽어 네이티브 코드로 변환

  • JIT (Just In Time) 컴파일러: 인터프리터 방식으로 실행하다가 적절한 시점에 바이트 코드 전체를 컴파일하여 기계어로 변경하고,
    이후에는 해당 더 이상 인터프리팅 하지 않고 기계어로 직접 실행하는 방식이다.

  • 가비지 콜렉터 (Garbage Collector)

    더 이상 사용하지 않는 메모리를 자동으로 회수한다.

6-3. 런타임 데이터 영역 (Runtime Data Area)

프로그램을 수행하기 위해 OS에서 할당받은 메모리 공간

모든 스레드가 공유해서 사용 (GC의 대상)

  • 메서드 역할 (Method Area)

  • 힙 영역 (Heap Area)

스레드(Thread) 마다 하나씩 생성

  • 스택 영역 (Stack Area)

  • PC 레지스터 (PC Register)

  • 네이티브 메서드 스택 (Native Method Stack)

6-3-1. 메서드 영역 (Method Area)

클래스 멤버 변수의 이름, 데이터 타입, 접근 제어자 정보와 같은 각종 필드 정보들과 메서드 정보, 데이터 Type 정보, Constant Pool, static변수, final class 등이 생성되는 영역

6-3-2. 힙 영역 (Heap Area)

new 키워드로 생성된 객체와 배열이 생성되는 영역
주기적으로 GC(Garbage Collector)가 제거하는 영역

  • Young Generation
    Minor GC = 생명주기가 짧은 젋은 객체를 GC대상으로 하는 가비지 콜렉트

    • Eden: 객체가 생성되면 최초 생성되는 공간
    • Survior: Eden에서 참조되는 객체들이 저장되는 공간
      Eden 영역에 데이터가 어느정도 쌓이게 되면 참조정도에 따라 Servivor의 빈 공간으로 이동되거나 회수된다.
  • Tenured Generation: Young Generation 영역이 차게 되면 참조정도에 따라 Old영역으로 이동 되게 되거나 회수왼다.
    Major GC = 생명주기가 긴 오래된 객체를 GC대상으로 하는 가비지 콜렉트

  • Permanent Generation: 생성된 객체들의 정보의 주소값이 저장된 공간
    클래스 로더에 의해 load되는 Class, Method 등에 대한 Meta 정보가 저장되는 영역, JVM에 의해 사용

6-3-3. 스택 영역 (Stack Area)

지역변수, 파라미터, 리턴 값, 연산에 사용되는 임시 값 등이 생성되는 영역

6-3-4. PC 레지스터 (PC Register)

Thread가 생성될 때마다 생성되는 영역으로 프로그램 카운터, 즉 현재 스레드가 실행되는 부분의 주소와 명령을 저장하고 있는 영역

6-3-5. 네이티브 메서드 스택 (Native Method Stack)

자바 프로그램이 컴파일되어 생성되는 바이트 코드가 아닌 실제 실행할 수 있는 기계어로 작성된 프로그램을 실행시키는 영역

7. JDK 와 JRE

7-1. JDK (Java Development Kit)

일반적으로 자바를 공부하기 위해 설치하는 것이 바로 JDK이다.
JDK는 JRE를 포함하고 있고, JRE는 JVM을 포함하고 있다.
JDK에는 JRE에는 없는 자바 컴파일러(Java Compiler)를 포함하고 있다.

JDK는 프로그램을 생성, 실행, 컴파일할 수 있다.
그래서 JDK를 설치하는 구나...

7-2. JRE (Java Runtime Environment)

자바 클래스 라이브러리(Java Class Libraries), 자바 가상 머신(JVM) 그리고 자바 클래스 로더(Java Class Loader)를 포함하고 있다.

컴파일 된 java 프로그램을 실행하는데 필요한 패키지이다.

profile
진짜 해보자

0개의 댓글