C와 C++의 경우 컴파일 플랫폼과 타겟 플랫폼이 다를 경우 프로그램이 동작하지 않을 수 있다. 여기서 환경이란 운영체제 + CPU 아키택처를 말한다.
이를 해결하기 위해 타겟 플랫폼에 맞춰 컴파일 해야되는데, 이것을 크로스 컴파일
이라고 한다.
후에 설명하겠지만 자바 바이트코드는 타겟 플랫폼에 상관 없이 JVM
위에서 동작한다.
즉 JVM이 타겟 플랙폼에 의존하여 대신해주는 것이다.
WORA
- Write Once, Run Anywhere (JVM이 있는 장착된 어떤 장비에서도 실행될 수 있다는 뜻)
-썬 마이크로시스템즈에 의해 만들어진 자바의 크로스/플랫폼에 의한 이익을 표현하기 위한 표어
즉 자바는 JVM
이 있는 모든 플랫폼에서 작동되는것이 목적이다.
compiler frontend = javac
<- 소스 코드 분석 (Analysis)
compiler backend = JVM
<- 어셈블리어로 바꾸는 곳 (Synthesis)
C의 경우 컴파일러가 해준다. 이 때 얻는 장점은 런타임 중 관여 할 수있다는 것이다.
Jvm
은 Java virtual Machine
의 약자로 자바 바이트코드를 실행할 수 있는 가상 환경Class Loader
)가 컴파일된 자바 바이트코드를 런타임 데이터 영역Runtime Data Areas
)에 로드하고, 실행 엔진Execution Engine
)이 자바 바이트코드를 실행한다. 정의: 자바의 동적 로드를 담당하는 부분이 JVM의 클래스 로더이다.
클래스 로딩을 하는 ClassLoader
가 하는 일은 위와 같이 크게 세 가지로 나뉘어진다.
Class Loader
가 하는 클래스 로딩과 관련된 일들은 한다.
Loading
의 특징으로는
계층 구조: 클래스 로더끼리 부모-자식 관계를 이루어 계층 구조로 생성된다.
(최상위 클래스 로더는 부트스트랩 클래스)
위임 모델(Delegation Hierarchy Model
): 계층 구조를 바탕으로 클래스 로더끼리 로드를 위임하는 구조로 아래와 같이
Bootstrap > Extension > Application(System) > Custom (Bootstrap이 우선순위가 높음)
Class Loader는 우선순위가 높은 클래스를 로딩한다.
Bootstrap Class Loader
자바에 기본적으로 내장되어 있는 클래스들을 로딩하는 Class Loader이다.
( JVM을 기동할 때 생성되며, Object 클래스들을 비롯하여 자바 API들)
이러한 내장 클래스들은 rt.jar라는 jar파일에 담겨져있다.
Extension Class Loader
$JAVA_HOME/lib/ext 디렉토리에 존재하는 클래스와
java.ext.dirs 시스템 변수에 저장된 클래스들을 로딩하는 Class Loader이다.
(기본 자바 API를 제외한 확장 클래스들을 로드한다. 다양한 보안 확장 기능)
Application Class Loader
애플리케이션 수준에 존재하는 클래스들을 로딩하는 Class Loader이다.
개발자가 직접 작성한 클래스들이 여기에 해당된다.
(사용자가 지정한 $CLASSPATH 내의 클래스들)
System Class Loader라고도 한다.
User-Defined Class Loader
애플리케이션 사용자가 직접 코드 상에서 생성해서 사용하는 클래스 로더이다.
가시성(Limit Visibility): 하위 클래스 로더는 상위 클래스 로더의 클래스를 찾을 수 있지만, 상위 클래스 로더는 하위 클래스 로더의 클래스를 찾을 수 없다.
언로드 불가(Unload Not Possiable): 클래스 로더는 클래스를 로드할 수는 있지만 언로드할 수는 없다. 언로드 대신, 현재 클래스 로더를 삭제하고 아예 새로운 클래스 로더를 생성하는 방법을 사용할 수 있다.
검증(Verifying): 읽어 들인 클래스가 JVM에 명시된 대로 잘 구성되었는지 검사하는 부분
준비(Preparing): 클래스가 필요로하는 메모리를 할당하는 부분
분석(Resolving): 클래스의 상수 풀 내 모든 심볼릭 레퍼런스를 메모리 상에서 실제로 존재하는 물리적인 주소로 변경하는 부분
클래스 파일이 JVM에 올라가게 되면 심볼릭 레펀선스는 실제 메모리 주소가 아닌 이름에 맞는 객체의 주소를 찾아서 연결하는 작업을 수행한다.
모든 스레드가 공유하는 영역으로, JVM이 시작될 때 생성된다.
Class Loader에서 로딩한 인터페이스, 클래스에 대한 메서드의 바이트 코드, static 변수 등을 관리하며, 그 중 런타임 상수 풀(Runtime Constant Pool)에서는 모든 메소드와 필드의 메모리 참조 를 담고 있는 테이블을 관리하여 메소드 참조시 JVM은 런타임 상수 풀(Runtime Constant Pool)을 통해 참조한다.
모든 스레드가 공유하는 영역이자, 인스턴스 또는 객체를 저장하는 공간으로 가비지 컬렉션 대상이다.
젊은 객체가 저장되어있는 곳 (여기서 일어나는 gc는 minor gc라고 불린다.)
Survivor 두 영역중 하나는 반드시 비어있는 상태다. 만약 두 영역에 모두 데이터가 존재하거나, 사용량이 0이라면 정상적인 상황이 아니다.
늙은 객체가 저장되어있는 곳 (여기서 일어나는 gc는 major gc라고 불린다.)
Metaspace는 Java의 Classloader가 현재까지 로드한 Class들의 Metadata가 저장되는 공간이다.
(Java 8 나오면서 JVM 영역에서 생긴 변화로, Permanent Generation 메모리 영역이 없어지고 Metaspace 영역이 생겼다.)
Permanent Generation 영역은 제한된 크기를 가지고 있어 OOM이 발생되었지만, MetaSpace로 바뀌면서 제한된 크기가 사라지고, Native 메모리 영역에 위치하게 되어 문제가 해결되었다.
(Heap 영역은 JVM에 의해 관리된 영역, Native 메모리는 OS에서 관리하는 영역으로 구분)
Stack Area는 Stack Frame을 저장하는 공간이며 Method Call당 하나씩 생성된다.
(스레드에 의해 이루어지는 모든 메서드 호출, 중간 계산, 로컬 변수의 할당, 호출 파라미터 등은 런타임 스택에 저장된다.)
스레드 당 하나의 Stack Frame을 가진다.
(스레드를 종료하기 직전 JVM은 스레드와 관련된 Stack을 삭제시킨다.)
스레드와 연결된 데이터를 저장하는 스택은 특정 스레드에만 독점적으로 사용할 수 있으며 다른 스레드에 액세스할 수 없다.(thread-safe)
설명: https://www.tutorialspoint.com/java-virtual-machine-jvm-stack-area
PC Registers는 Thread가 생성될 때 마다 생기는 공간으로 Thread가 어떠한 명령을 실행하게 될지 기록을 한다.
자바 이외의 언어(C, C++, 어셈블리 등)로 작성된 코드를 실행할 때, Native Method Stack이 할당된다.
(일반적인 메소드를 실행하는 경우 JVM 스택에 쌓이다가 해당 메소드 내부에 네이티브 방식을 사용하는 메소드(예를 들면 C언어로 작성된 메소드)가 있다면 해당 메소드는 네이티브 스택에 쌓인다.)
이 때 JNI (Java Native Interface) 규격에 맞게 적절하게 변경해야 한다.
Execution Engine은 바이트 코드를 실행하는 주체이다.
Runtime Data Area에 존재하는 Method Area의 바이트 코드를 가져와서 실행하게 된다.
이 때, Load 된 바이트코드를 실행하는 Runtime Module이 Execution Engine(실행 엔진) 이다.
Execution Engine이 바이트 코드를 해석하는 방법은 두 가지가 있다.
Interpreter 방식은 바이트 코드를 한 줄 한 줄 해석하며 실행하는 방식으로 느리다는 단점이 있다.
속도를 개선하기 위해 바이트코드를 JIT 컴파일러를 이용해 프로그램을 실제 실행하는 시점(바이트코드를 실행하는 시점)에 각 OS에 맞는 Native Code로 변환하였다.
하지만, 바이트코드를 Native Code로 변환하는 데에도 비용이 소요되므로, Interpreter와 함께 사용한다.
(보통 일정 수준까지 Interpreter 사용 후 넘어가면 사용한다.)
Reference
[NAVER D2 - JVM Internal]
https://d2.naver.com/helloworld/1230
[JVM, 그래서 넌 뭐야]
https://velog.io/@dhwlddjgmanf/JVM-%EA%B7%B8%EB%9E%98%EC%84%9C-%EB%84%8C-%EB%AD%90%EC%95%BC
[JVM Structure]
https://dzone.com/articles/jvm-architecture-explained
[Minor GC vs Major GC vs Full GC]
https://plumbr.io/blog/garbage-collection/minor-gc-vs-major-gc-vs-full-gc
[10분 테코톡 - 무민의 JVM]
https://www.youtube.com/watch?v=UzaGOXKVhwU&ab_channel=%EC%9A%B0%EC%95%84%ED%95%9CTech