티스토리 뷰
백기선님의 강의 <더 자바, "코드를 조작하는 다양한 방법">의 1부 JVM 이해하기를 보고 작성한 글입니다.
1. JAVA, JVM, JDK, JRE
JVM (Java Virtual Machine)
- 자바 가상 머신으로 자바 바이트 코드(.class 파일)를 OS에 특화된 코드(머신 코드)로 변환(인터프리터와 JIT Compiler)하여 실행한다.
- 바이트 코드를 실행하는 표준이자 구현체(특정 벤더가 구현한 JVM)다.
- JVM 밴더 : 오라클, 아마존, Azul.. etc
- 특정 플랫폼(OS : Windows, MacOS .. etc)에 종속적이다.
JRE(Java Runtime Environment) : JVM + 라이브러리
- 자바 애플리케이션을 실행할 수 있도록 구성된 배포판.
- JVM과 핵심 라이브러리 및 자바 런타임 환경에서 사용하는 프로퍼티 세팅이나 리소스 파일을 가지고 있다.
- 개발 관련 도구는 포함하지 않는다.( 그건 JDK에서 제공한다. )
>>JRE의 목적은 자바 애플리케이션을 실행하는 것이다. JRE에는 java가 있지만, 컴파일하는 javac는 들어가 있지 않다.
JDK(Java Development Kit) : JRE + 개발 툴
- JRE + 개발에 필요할 툴
- 소스 코드를 작성할 때 사용하는 자바 언어는 플랫폼에 독립적
- 오라클은 자바 11부터는 JDK만 제공하며 JRE를 따로 제공하지 않는다.
- Write Once Run Anywhere
JAVA
- 프로그래밍 언어
- JDK에 들어있는 자바 컴파일러(javac)를 사용하여 바이트코드(.class 파일)로 컴파일 할 수 있다.
- 자바 유료화? 오라클에서 만든 Oracle JDK 11버전부터 상용으로 사용할 떄 유료이다.
>> 위 조건에 하나라도 일치 하지 않는다면 무료
JVM 언어
- JVM 기반으로 동작하는 프로그래밍 언어
- 클로저, 그루비, JRuby, Jython, Kotlin, Scala... etc
>> 최초 JVM은 자바만을 위해 만들어졌었는데, 자바와의 의존성이 그리 타이트하지 않다. 클래스를 만들어야 하는 언어라면 JVM기반으로 작성할 수 있다.
2. JVM 구조
클래스 로더 시스템 : 자바 바이트 코드를 읽어들여서 메모리에 적절하게 배치
- 로딩 : .class에서 바이트코드를 읽는 역할
- 링크 : 레퍼런스를 연결
- 로더 : static 값 값들 초기화 및 변수에 할당
메모리 :
- 메소드 영역: 클래스 수준(클래스 이름, 풀 패키지 경로, 부모 클래스 이름(상속받을 시), 메서드, 변수 ) 저장, 공유 자원이다. 메소드 영역은 JVM이 시작할 때 생성되고 모든 스레드가 공유하는 영역이다.
- 힙 영역 : 객체(인스턴스)를 저장, 공유 자원이다. 힙 영역에 생성된 객체와 배열은 JVM 스택 영역의 변수나 다른 객체의 필드에서 참조한다. 참조하는 변수나 필드가 없다면 의미없는 객체가 되기 때문에 쓰레기로 취급하고 GC(Garbage Collector)를 실행시켜 쓰레기 객체를 힙 영역에서 자동으로 제거한다.
- 스택 영역: 각 쓰레드마다 하나씩 존재하며 쓰레드가 시작될 때 할당된다. 자바 프로그램에서 추가적으로 쓰레드를 생성하지 않았다면 main 쓰레드만 존재하므로 JVM 스택도 하나이다. JVM스택은 메소드를 호출할 때 마다 그안에 스택 프레임(frame)을 추가(push)하고 메소드가 종료되면 해당 프레임을 제거(pop)하는 동작을 수행한다.
ex) 예외 발생시 printStackTrace() 메소드로 보여주는 Stack Trace의 각 라인은 하나의 프레임을 표현한다.
- PC(Program Counter) 레지스터: 쓰레드 마다 쓰레드 내 현재 실행할 스택 프레임을 가리키는 포인터가 생성된다.
- 네이티브 메소드 스택 : 네이티브 메서드를 호출할 떄 사용하는 별도의 메서드 스택이다.
>>> 스택 , PC, 네이티브 메소드 스택은 쓰레드에서만 공유한다. 힙이나 메서드 처럼 모든 영역에 공유하지 않는다.
실행엔진
- 인터프리터 : 바이트 코드를 한줄씩 실행(한줄 한줄 컴파일 하여 실행)
- JIT컴파일러 : 인터프리터 효율을 높이기 위해, 인터프리터가 반복되는 코드를 발견하면 반복되는 코드를 모두 네이티브 코드로 바꿔준다.
>>> 실행 속도 향상 시키는 역할
- GC(Garbage Collector): 더 이상 참조되지 않는 객체를 모아서 정리한다.
JNI(Java Native Interface)
- 자바 애플리케이션에서 C, C++, 어셈블리로 작성된 함수를 사용할 수 있는 방법 제공
- Native 키워드를 사용한 메소드 호출
네이티브 메소드 라이브러리
- C, C++로 작성된 라이브러리
※ 네이티브 메서드
- 네이티브 메서드는 자바가 아니라 C로 구현한 것이다.
ex) 자바의 Thread.currentThread();
- 네이티브 메서드를 써야 하는 코드가 있다면, 네이티브 메서드 스택이 생기며 그안에 네이티브 메서드 인터페이스를 호출하는 스택 프레임이 쌓이고 JNI를 이용해 네이티브 메소드 라이브러리를 사용한다.
JVM의 전체적인 흐름은 클래스 로더가 바이트 코드를 읽어서 메모리에 배치한다. 그리고 실행할 때 쓰레드가 만들어지면 스택, PC 등이 만들어 지고 실행엔진이 바이트 코드를 실행한다. 실행하며 JIT Compiler와 GC 등을 사용하고, 네이티브 라이브러리를 사용하면 JNI를 이용한다.
이미지 출처 : https://dzone.com/articles/jvm-architecture-explained
3. 클래스 로더
- 로딩, 링크, 초기화 순으로 진행한다.
로딩
- 클래스 로더가 .class파일을 읽어서 그 내용에 따라 적절한 바이너리 데이터를 만들고 메서드 영역에 저장
- 메서드 영역에 저장하는 데이터
1. FQCN
2. 클래스, 인터페이스, 이늄인지에 대한 정보
3. 메서드와 변수
- 로딩이 끝나면 해당 클래스 타입의 class 객체를 생성하여 힙 영역에 저장
링크
-Verify, Prepare, Resolve(optional) 세 단계로 나눠져 있다.
1. verify: .class 파일 형식이 유요한지 체크한다.
2. Prepare : 클래스 변수(static 변수)와 기본값에 필요한 메모리를 준비하는 과정
3. Resolve : 심볼릭 메모리 레퍼런스를 메소드 영역에 있는 실제 레퍼런스로 교체한다.
>> 이 과정은 옵션이다. 심볼릭 레퍼런스란 어떤 객체가 다른 객체를 참조할 떄 실제 레퍼런스를 가리키는 것이 아닌 논리적인 레퍼런스이다. 이 단계에서 실제 객체를 참조할 수 있도록 할 수도 있고 아닐 수도 있다.
초기화
- 준비된 메모리 영역에 static변수의 값을 할당한다.(static 블럭이 있따면 이떄 실행)
ex) static String name = "it"; 호출
클래스 로더 구조
클래스 로더는 계층 구조로 이뤄져 있으며 기본적으로 세가지 클래스 로더가 제공된다.
- 부트 스트램 클래스 로더 : JAVA_HOME\lib에 있는 코어 자바 API를 제공한다. 최상위 우선순위를 가진 클래스 로더
- 플랫폼 클래스 로더 : JAVA_HOME\lib\ext 폴더 또는 java.ext.dirs 시스템 변수에 해당하는 위치에 있는 클래스를 읽는다.
- 애플리케이션 클래스 로더 : 애플리케이션 클래스패스(애플리케이션 실행시 주는 -classpath 옵션 또는 java.class.path환경 변수의 값에 해당하는 위치)에서 클래스를 읽는다.
위 세가지 과정에서도 클래스를 읽지 못하면 ClassNotFoundException 발생.
출처 : 더 자바, "코드를 조작하는 다양한 방법" 1부 JVM 이해하기 - 백기선
이것이 자바다 신용권의 Java 프로그래밍 정복 1 - 신용권
'jvm언어관련 > java' 카테고리의 다른 글
Slf4j MDC(Mapped Diagnostic Context) 사용 (1) | 2020.12.07 |
---|---|
javax.imageio.IIOException: Unsupported Image Type (0) | 2019.12.27 |
java.lang.UnsupportedClassVersionError (0) | 2019.09.17 |
javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure (0) | 2019.07.23 |
@NotEmpty @NotNull @NotBlank (0) | 2019.06.12 |
- Total
- Today
- Yesterday
- 이것이 자바다
- visual studio code
- 이펙티브자바
- SpringBoot
- vue.js
- 다중 업데이트
- update query mutiple row
- gradle
- 뱅크샐러드 유전자
- update set multiple
- Slack
- 그레이들
- java
- 슬랙봇
- 업데이트 쿼리
- update set multi
- spring-boot-starter-data-redis
- update query
- 뱅셀 유전자
- update query set multiple
- springboot https
- 슬랙
- 뱅크샐러드
- 몽고DB 완벽가이드
- MSSQL
- update query multi row
- effectivejava
- 슬랙 /
- multiple row update
- 싱글턴
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |