일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- Elk
- JWT
- 최종 합격
- Kotlin
- 동시성문제
- tomcat
- 우아한 테크 코스
- resilience4j
- spirng
- 트랜잭션
- Thread
- Gateway
- 톰캣
- 살아남았다.
- Spring cloud gateway
- 테스트코드
- circuitbreaker
- Transactio
- Spring Batch
- 오어스
- redis
- AOP
- MDC
- DispatcherServlet
- HikariCP
- 커넥션 풀
- 우테코 5기
- 우테코
- oauth
- 우아한테크코스
- Today
- Total
코딩은 내일부터
JVM 알아보기 본문
JVM이란?
- JVM은 Java Virtual Machine의 약자로 자바 애플리케이션이 수행되는 런타임 엔진을 의미
- JVM은 JRE(Java Runtime Environment)의 일부분에 속함
- Java는 os에 종속적이지 않다는 특징을 가지고 있다. OS 위에서 Java를 실행시킬 무언가가 필요한데 그게 JVM이다. 다시 말해서 JVM을 이용해서 Java는 OS에 종속적이지 않고 실행할 수 있는 것이다..
Java 소스코드(.java)는 CPU가 인식하지 못해서 기계어로 컴파일해줘야 한다.
여기서 Java는 바로 기계어로 이루어진 binary code로 변환하는 게 아닌 JVM이 인식할 수 있는 byte code(.class)로 변환한다.
자바 컴파일 절차
Java compiler는 JDK에 있는 javac.exe 파일의 의해 소스코드에서 바이트 코드로 변환된다.
JVM
JVM의 Architecture는 위 그림과 같다. 먼저 JVM의 메모리 영역에 대해 알아보겠다.
JVM의 메모리 영역
- Method(class) area
- 클래스, 변수의 틀이 저장
- Heap area
- object들이 저장되는 곳
- Stack area
- 쓰레드 별로 사용하는 저장소
- PC Registers
- 쓰레드의 execution instruction정보의 위치 저장
- Native method stacks
- 자바 코드가 아닌 native 메소드 정보 저장
클래스로더의 로딩 절차
위에 JVM Architecture를 보면 Classloader라는 게 있는데 이 Classloader는 런타임 중 동적으로 자바 클래스들을 JVM에 로딩하는 역할을 담당한다.
즉, Java클래스는 한 번에 메모리에 올라가지 않고, 클래스 로더에 의해 애플리케이션에서 필요할 때만 메모리에 올라가게 된다.
클래스로드 로딩과정의 대해 알아보겠다.
위와 같이 3가지의 단계로 나뉜다.
- Loading
- 클래스로더는 .class 파일을 읽는다.
- 바이너리 코드들을 읽어서 Method(class) area에 저장한다.
- 패키지명, 클래스명 저장
- class, interface, enum여부를 저장
- 부모 클래스 정보도 저장
- 접근제어자, 변주, 메소드 정보 등 저장
- Heap메모리에 Class 타입의 객체를 저장한다.
- Linking
해당 과정에서는 3단계를 거쳐서 진행된다.
- Verification
- .class파일이 제대로 된 클래스 파일인지 검증
- 클래스 파일은 언제든 변조가 가능하다. 그래서 마음대로 변조했을 때 원하는 결과를 제공하지 못할 수도 있고, 변조된 클래스파일이 JVM에 올라가면 JVM이 치명적인 손상을 입어서 다운될 수도 있다.
- 이 과정에서 오버헤드가 발생하기 때문에 클래스 패스에 믿을 수 있는 클래스 파일만 있는 경우 하면 성능 향상을 위해 진행하지 않도록 설정할 수 있다.(-Xverify:none)
- ByteCodeVerifier라는 컴포넌트를 통해서 진행
- 이 단계를 거친 후 컴파일 준비가 끝남
- .class파일이 제대로 된 클래스 파일인지 검증
- Preparation
- 클래스에 있는 static변수들을 기본값으로 메모리에 할당(값을 넣지 않음)
- Resolution
- 해당 타입의 기호 참소를 직접 참조로 변경
- 참조되는 엔티티들은 Method(Class) area를 검색하여 수행
- Initializing
- Preparation단계에서 확보한 메모리 영역에 static값으로 할당한다.
- 부모클래스와 자식클래스를 초기화를 진행한다.
Class loader의 종류
Bootstrap class loader
자바가 설치된 경로(JAVA_HOME)/jre/lib에 있는 파일들을 로드
- 이 경로를 bootstrap path라고 부름
- C/C++과 같은 네이티브 언어로 되어 있음
Extension class loader
- Bootstrap class loader의 자식 클래스 로더
- JAVA_HOME/jre/lib/ext에 있는 파일들을 로드(혹은 java.extdirs속성값에 지정된 경로에 있는 파일들을 로드)
- sun.misc.Launcher$ExtClassLoader를 통해 작업 수행
System.Application class loader
- Extension class loader의 자식 클래스 로더
- 애플리케이션의 classpath에 지정된 클래스들을 로드
- sun.misc.Launcher$AppClassLoader를 통해 작업 수행
애플리케이션을 구동을 위해 직접 작성한 대부분의 클래스는 이 애플리케이션 클래스로더에 의해 로딩된다.
실행 엔진
이제 클래스를 로드하고 실행시키는 역할이 남았다.
클래스 로더가 JVM내에 런타임 데이터 영역에 바이트 코드를 배치시키고, Execution Engine으로 실행시킨다.
이때 Execution Engine은 바이트코드를 바이너리 코드로 변환이 일어난다.
실행 엔진은 다음의 2가지로 구성된다.
Interpreter
- 바이트 코드를 라인단위로 읽어서 번역하고 실행
- 반복되는 부분이 있어도 계속 번역작업 수행
Just-In-Time
Compiler(JIT)
- interperter를 효율적으로 활용하기 위해서 사용
- 모든 바이트코드를 컴파일한 후 네이티브 코드로 변경
- interpreter가 반복적인 메서드 호출이 있을 때 JIT에서
- 해당 부분에 대한 네이티브 코드를 제공
정리를 하면 Interpreter를 사용해서 번역을 진행다가 반복적인 작업이 일어나면 JIT로 번역이 일어난다.
보통 1만 번 반복되면 그 작업에서 JIT가 활성화된다.
그 몇 번을 반복할지는 -XX:CompileThreshold라는 명령어를 통해서 횟수를 정할 수 또 있다.
처음에 서버를 내렸다 올리면 처음에 요청이 오면 CPU가 100% 차는 거를 느꼈을 거다 그 이유가 웜업 단계라고 표현하는데 Interpreter로 동작하고 있다가 어느 정도 많이 사용하면 JIT로 전환이 되는 과정을 진행한다.
가급적이면 JVM을 띄우고 부하테스트 도구나 테스트 도구를 통해서 웜업 시켜주는 게 좋다.
BCI기술
- BCI는 Byte Code Instrumentation의 약자로 클래스 파일을 로딩할 때 내용을 변조하는 기술이다.
- BCI는 Java의 Byte Code에 대해 직접적으로 수정을 가해서, 소스 파일의 수정 없이 원하는 기능을 부여하는 기법이다.
- BCI를 주로 사용하는 곳
- APM
- AOP (Aspect Oriented Programming)
이상!