운영체제와 하드웨어에 독립적으로 동작하며 자바 코드를 실행하기 위해 필요한 라이브러리 및 기능을 제공함
자바 바이트코드를 실행하는 역할을 수행함
컴파일 하는 방법
javac(java compiler)를 사용하여 컴파일
일반적으로 상위버전으로 컴파일된 클래스파일은 하위버전에서 동작하지 않지만 컴파일 시 -target 옵션을 설정하여 호환 가능하게 만들 수 있음
버전이 올라갈수록 javac의 성능도 올라가므로 버전을 낮춰서 호환시켜야 하는 상황이 아니면 하지 않는게 좋음
java 파일을 컴파일시키면 .class확장자를 가진 자바 바이트코드가 만들어짐
javap -c Main.class 를 사용하여 클래스 파일을 OP(operation code)코드를 사용하여 읽기 쉽게 보여줌
//상위 버전으로 컴파일된 클래스파일을 하위 버전에서 동작시 발생하는 에러
//에러 메시지를 읽어라
Error: A JNI error has occurred, please check your installation and try again
Exception in thread "main" java.lang.UnsupportedClassVersionError: Main has been compiled by a more recent version of the Java Runtime (class file version 57.0), this version of the Java Runtime only recognizes class file versions up to 52.0
실행하는 방법
Main.class파일 실행 -> java Main
Java 파일 실행 과정
소스코드 작성 - .java 확장자를 가지는 텍스트 파일 작성
컴파일 - javac를 사용하여 .class확장자를 가지는 바이트코드로 변환
클래스 로딩 - JVM 클래스 로더를 사용하여 필요한 클래스 파일을 로드, 로드된 클래스 파일은 런타임 데이터 영역에 저장
바이트코드 검증 - 로드된 바이트코드를 검증(올바른 형식인지, 오류가 있는지 등)
실행 엔진에 의한 바이트코드 실행 - 인터프리터로 실행하거나, JIT 컴파일러를 사용하여 네이티브 코드로 변환하여 실행
바이트코드란 무엇인가
JVM이 이해할 수 있는 언어(바이너리 코드 2진수로 되어있음)
바이트코드는 기계어가 아니기 때문에 OS에서 바로 실행할 수 없음
자바 소스 코드를 컴파일하여 생성되는 중간 형식의 코드로, 기계어보다는 약간 더 추상화된 형태
JVM이 해독할 수 있는 바이트코드만 만들 수 있다면 kotlin, groovy 등 다른 언어들을 사용해도 됨
JIT 컴파일러란 무엇이며 어떻게 동작하는지
Just In Time 컴파일러
반복되는 코드, 자주 사용되는 코드를 JIT 컴파일러가 자바 바이트코드를 기계어로 변환해서 컴파일한 후 JVM Runtime 영역에 캐싱하여 재사용함
기계어로 인터프리터가 해석할 필요 없이 기계어가 바로 실행을 하여 속도가 빨라짐
인터프리터는 자바 바이트코드를 한줄 씩 실행, 전체 성능면에서 불리함
프로그램을 실행하는 시점에 동작함
JVM은 내부적으로 해당 메서드가 얼마나 자주 수행되는지 체크하고 일정 정도를 넘을 때만 컴파일 수행
JVM 구성 요소
Class Loader
클래스 로더는 JVM이 실행할 클래스 파일을 로드함
클래스 파일을 찾고, 검증하고, JVM이 사용할 수 있는 형식으로 반환함
Execution Engine
클래스 파일에서 바이트코드를 실행함
바이트코드를 인터프리터로 실행하거나, JIT 컴파일러를 사용하여 네이티브 코드로 변환하여 실행함
GC(Garbage Collector): 자동으로 더 이상 사용되지 않는 객체를 메모리에서 제거하여 메모리 누수를 방지함
Runtime Data Area
JVM이 실행하는 Java 프로그램에 필요한 데이터를 저장하는 메모리 공간
메소드 영역, 힙 영역, 스택 영역 등이 있음
메소드 영역 : 클래스 파일에서 로드된 클래스, 인터페이스, 메소드, 상수 등의 정보를 저장
힙 영역 : 객체 인스턴스가 생성되는 메모리 공간, 가비지 컬렉터를 사용하여 힙 영역에서 더 이상 사용되지 않는 객체를 제거
스택 영역 : 메소드 호출에 따라 생성되는 지역 변수, 매개 변수, 리턴 값 등을 저장, 각 스레드마다 별도로 존재함
Native Method Interface
Java 코드에서 C, C++, 어셈블리 등의 네이티브 코드를 호출할 수 있는 인터페이스를 제공
Java 언어로 작성할 수 없는 시스템 라이브러리 및 하드웨어를 사용할 수 있음
JDK와 JRE의 차이
JDK(Java Development Kit) = 자바 개발 도구 = 자바 애플리케이션을 개발하는 데 필요한 모든 도구와 라이브러리를 포함함
JRE(Java Runtime Environment) = 자바 실행 환경 = 자바 애플리케이션을 실행하는 데만 필요함
JDK > JRE
JDK는 JRE를 포함하여 추가로 Javac, Jar, Javadoc, 디버깅 도구, 프로파일링 도구, 테스트 도구 등을 제공함