Notice
Recent Posts
Recent Comments
Link
nathan_H
[Java] Java 애플리케이션에서 JVM 구조와 실행 과정 본문
JVM 이란?
- Java Virtual Machine의 약자로 자바 바이트 코드를 OS에 특화된 코드로 변환하여 실행 해주는 역할.
- 즉, JVM 위에서 동작하기 위해서는 자바 바이트코드가 필요함.
- 자바 바이트 코드는 개발자에 의해서 작성된 자바 코드를 자바 컴파일러로 변환 된 코드를 말함
- 바이트 코드를 실행하는 "표준"이자 "구현체"
- JVM 표준 스택에 따라 다양한 밴더가 제공이 되고 있음
- 오라클, 아마존 등등
- JVM 표준 스택에 따라 다양한 밴더가 제공이 되고 있음
- JVM은 OS에 특회된 코드로 변환해 실행을 해주기 때문에 특정 플랫폼에 종속적인 특징을 가지고 있음
- 이것의 의미는 자바에서는 JVM에 의해서 실행이 되기 때문에 자바는 운영체제에 독립적이라고 할 수 있음
JRE, JDK, Java
The Secret of Java- JDK, JRE, JVM difference
- JVM 구조에 대해 자세히 들어가기 전에 위 JRE, JDK, Java에 대한 명확한 구분과 정의를 알 필요가 있다.
JRE
- Java Runtime Environment로 JVM + 라이브러리로 구성되어져 있음
- JVM과 핵심 라이브러리 및 자바 런타임 환경에서 사용되는 프로퍼티 세팅이나 리소스 파일을 가지고 있으며 개발 관련 도구가 포함되어 있지 않는 실행 환경이라고 볼 수 있음
JDK
- Java Development Kit : JRE + 개발에 필요한 툴
- 단어 뜻 그대로 자바 개발을 위한 도구이며, Java Complier, Debugger, JVM, 각종 Library 등을 포함하고 있음
- 참고로, 오라클은 자바 11부터 JDK만 제공하며 JRE는 따로 제공하지 않음
- JRE가 점점 사라지는 추세
Java
- 자바는 프로그래밍 언어로써, JDK에 들어있는 자바 컴파일러를 사용하여 바이트코드(.class)로 컴파일 할 수 있음
- 자바라는 단어 하나로 JDK, JRE와 함께 포괄적으로 말하는 경우가 있는데, 자바는 단순히 프로그래밍 언어 중 하나일 뿐 JDK의 컴파일러를 사용해 바이트 코드로 컴파일 한 후 JVM에 의해 실행이 됨
- Java 코드 → JDK 컴파일러로 바이트 코드 생성(.class 파일) → JVM → 실행
JVM 구조
https://www.guru99.com/java-virtual-machine-jvm.html
클래스 로더 시스템
- .class 에서 바이트코드를 읽고 메모리에 저장하는 시스템
- 로딩 : 클래스를 읽어오는 과정
- 링크 : 레퍼런스를 연결하는 과정
- 초기화 : static 값들 초기화 및 변수에 할당
- 즉 생성된 클래스 파일들을 엮어 JVM이 운영체제로부터 할당받은 메모리 영역에 적재하는 역할을 하는 시스템
메모리
https://minwan1.github.io/2018/06/06/2018-06-06-Java,JVM/
-
JVM의 메모리 영역으로 자바 애플리케이션을 실행할 때 사용되는 데이터들을 적재하는 영역
-
메소드 영역
- 클래스 수준의 정보를 저장
- 클래스 수준의 정보 : 클래스 이름, 부모 클래스 이름, 메소드 이름(접근 제어자 정보 포함), 변수
- 클래스 수준의 정보를 저장
-
힙 영역
- 객체를 저장, 공유하는 자원
- 인스턴스"객체"와 배열이 생성되는 영역으로, 메소드 영역에 로드된 클래스만 생성이 가능하고 GC에 의해서 참조되지 않는 메모리를 확인하고 제거하는 영역
-
스택 영역
- 쓰레드 마다 런타임 스택을 만들고, 그 안에 메소드 호출을 스택 프레임이라 부르는 블록을 쌓는 곳으로 지역 변수, 파라미터, 리턴 값, 연산에 사용되는 임시 값등이 생성되는 영역
- 쓰레드가 종료되면 런타임 스택도 함께 사라짐
-
PC 레지스터
- 쓰레드 마다 쓰레드 내 현재 실행할 스택 프레임을 가리키는 포인터가 생성되는 영역
- 현재 쓰래드가 실행되는 부분의 주소와 명령어를 저장
- 쓰레드 마다 쓰레드 내 현재 실행할 스택 프레임을 가리키는 포인터가 생성되는 영역
-
네이티브 메소드 스택
- 자바 외 언어로 작성된 네이티브 코드(C/ C++ 등)를 위한 메모리 영역
Stack vs Head
class Person {
String name;
}
public class Main {
public static void main(String[] args) {
Person p = new Person();
String name = "Nathan";
p.name = name;
}
}
- 위 코드에서 new Person()으로 생성된 인스턴스는 힙 영역에 저장이 되며 힙 영역에 저장된 주소 값을 가지고 있는 p라는 지역 변수는 Stack 영역에 저장이 되어 있음.
실행 엔진
-
클래스 로더를 통해 JVM 내의 메모리 영역에 배치된 바이트 코드를 실행하는 역할
- 실행 엔진은 자바 바이트 코드를 기계어로 변경한 뒤에 사용
-
인터프리터
- 바이트 코드를 한 줄 씩 실행
-
JIT 컴파일러
- 인터프리터의 효율을 높이기 위해, 인터프리터가 반복되는 코드를 발견하면 JIT 컴파일러로 반복되는 코드를 모두 네이트브로 바꿔두는 역할
-
Garbage Collector
-
자바 어플리케이션에서 사용하지 않는 메모리를 자동으로 수거하는 기능으로 더이상 참조되지 않는 개체를 모아서 정리하는 역할
GC의 실행 순서
- 참조되지 않는 객체를 탐색 후 삭제
- 삭제된 객체의 메모리를 반환
- Heap 메모리의 재사용
-
JNI
- Java Native Interface의 약자로 자바 애플리케이션에서 C, C++, Assmebly로 작성된 함수를 사용할 수 있는 방법을 제공하는 일종의 프레임 워크
- Native 키워드를 사용한 메소드 호출
Native Method Libraries
- 네이티브 메소드 실행에 필요한 라이브러리
클래스 로더 시스템 이해하기
-
클래스 로드는 로딩 → 링크 → 초기화 순서로 진행이 됨
-
로딩
- 클래스 로더가 .class 파일을 읽고 그 내용에 따라 적절한 바이너리 데이터를 만들고 “메소드” 영역에 저장.
- 이때 메소드 영역에 저장하는 데이터
- FQCN (Fully Qualified Class Name)
- 클래스 | 인터페이스 | 이늄
- 메소드와 변수
- 로딩이 끝나면 해당 클래스 타입의 Class 객체를 생성하여 “힙" 영역에 저장.
-
링크
- Verify, Prepare, Resolve(optional) 세 단계로 나눠져 있다.
- 검증: .class 파일 형식이 유효한지 체크한다.
- Preparation: 클래스 변수(static 변수)와 기본값에 필요한 메모리
- Resolve: 심볼릭 메모리 레퍼런스를 메소드 영역에 있는 실제 레퍼런스로 교체한다.
-
초기화
- Static 변수의 값을 할당한다. (static 블럭이 있다면 이때 실행된다.)
클래스 로더 계층 구조
https://www.javatpoint.com/classloader-in-java
-
클래스 로더는 계층 구조로 이뤄져 있으면 기본적으로 세가지 클래스 로더가 제공된다.
- 부트 스트랩 클래스 로더 - JAVA_HOME\lib에 있는 코어 자바 API를 제공한다. 최상위 우선순위를 가진 클래스 로더
- 플랫폼 클래스로더 - JAVA_HOME\lib\ext 폴더 또는ext.dirs 시스템 변수에 해당하는 위치에 있는 클래스를 읽는다.
- 애플리케이션 클래스로더 - 애플리케이션 클래스패스(애플리케이션 실행할 때 주는 -classpath 옵션 또는class.path 환경 변수의 값에 해당하는 위치)에서 클래스를 읽는다.
-
클래스 로더 같은 경우 동적 로딩으로 진행이 되는데, 동적 로딩의 경우는 아래 글을 참고하길 바란다.
마무리
- 위에서 언급했듯이 자바를 JVM, JDK 등과 함께 포괄적으로 말하는 경우가 있지만 자바 자체로는 프로그램을 실행할 수는 없다. 그래서 우리는 JDK 을 통해 컴파일러로 자바 소스 코드를 컴파일 한 후 바이트 코드를 생성해 JVM에게 바이트 코드를 OS에 특화된 코드로 변환해 실행해 달라고 요청을 하는 것이다.
- JVM 구조 각각의 내용을 모두 자세히 알 필요는 없으나 Java를 통해 실제 프로그램을 구현하기 위해서는 JVM의 구조와 작동 방식에 대한 기본적인 이해를 할 필요는 있다.
- 다음에는 JVM의 핵심인 바이트 코드에 대해서 다룰 예정이다.
참고
'Programming Laguage > Java' 카테고리의 다른 글
인터페이스의 개념과 추상 클래스와의 차이점 (0) | 2020.06.02 |
---|---|
[Java] 바이트코드 조작 (0) | 2020.05.08 |
[Java] 상속 핵심 개념과 추상 클래스 (0) | 2020.05.01 |
[Java] 빠르게 정리하는 자바 클래스 (0) | 2020.04.28 |
[Java] Call By Value와 Call By Reference (0) | 2020.04.27 |
Comments