Java week1
1주차
JVM이란 무엇인가
컴파일 하는 방법
실행하는 방법
바이트코드란 무엇인가
JIT 컴파일러란 무엇이며 어떻게 동작하는지
JVM 구성 요소
JDK와 JRE의 차이
JVM이란 무엇인가
Java Virtual Machine
읽어보기: 모든 프로그램 및 프로그래밍 코드는 CPU에서 동작한다. C 계열(native code)은 CPU에서 바로 동작이 가능하다. 반면 특히 Java 언어 혹은 JVM 언어라 불리우는 코드들은 byte code로 구성되어 실행시킬 가상 머신이 필요한데 즉 JVM이라고 불린다. 이 말은 C 계열의 native code 들은 cpu와 OS에 종속적이다. 프로그램이 컴파일되면서 실행되는 환경(플랫폼)에 종속적이게 된다. JVM 언어들은 JVM위에서 동작하기 때문에 플랫폼에 종속적이지 않다.
이 말은 OS에 맞게 해석 해주는 역할
을 담당하기 때문이다.JVM은 OS에 종속적이지만 동일한 실행 결과를 보장
한다. JVM이라는 녀석이 중간에 끼어있다보니 느리다는 인식이자 사실이 있다.역할: Javac(Compiler)가 프로그래머가 작성한 .java 파일을 byte code인 .class 파일로 변환해주고, byte code를 OS에 상관없이 해석하여 실행하도록 해준다.
설치: JDK와 JRE를 설치하면 자동으로 설치된다.
- JDK와 JRE는 하단에서 다시 설명
컴파일 하는 방법
- CLI
➜ javac *.java
실행하는 방법
- 확장자 .class를 제외하고 아래와 같이 실행
➜ java HelloWorld
바이트코드란 무엇인가
- 바이트 코드: 플랫폼에 종속적이지 않는 이진코드로 cpu가 이해하는 것이 아니라 JVM 같은 가상 머신이 이해가능한 코드 ex) 자바 바이트 코드
- 바이트 코드는 ClassLoader에 의해서 JVM의 Runtime Data Area 에 올라가게 됨
- 바이너리 코드: 기계어 0과 1로 이루어진 이진코드
JIT 컴파일러란 무엇이며 어떻게 동작하는지
읽어보기: 기계어로 빠르게 변환해주는 JVM 내부의 최적화된 컴파일러. Run Time 중에 JVM에서 돌아가는 자바 바이트 코드를 플랫폼에 맞는 네이티브 코드(기계어)로 컴파일 해준다. 즉 자바 바이트 코드 -> 기계어로 컴파일 하는 시간이 있는 만큼 느리다는 생각이 있지만, JIT 컴파일러는 JRE의 일부로서 바이트 코드를 컴파일하는 과정에서 최적화하여 속도를 향상 시켜준다.
동작방식: JIT Compiler는 유사한 바이트코드를 매번 다시 컴파일하지 않고, 캐싱해둬서 컴파일에 필요한 총 시간을 단축한다. 참고: https://lazymankook.tistory.com/79
JVM 구성 요소
Class Loader
: JVM Run Time Area에 *.java를 런타임에 로딩한다.Execution Engine
: *.java 를 기계어(네이티브 코드)로 변환하여 실행한다. Interpreter 즉 명령을 순차로 읽으면서 실행한다. main 함수를 포함해야 한다.Garbage Collector
: 동적으로 할당한 Heap 메모리 영역에서 사용하지 않은 (참고되지 않는) 메모리를 해제하는 기능. 즉 Stack 영역을 스캔하여 Heap에서 참조되지 않는 객체를 Heap에서 날림- Mark(사용하는 객체가 있는지 탐색하고 체크) & Sweep (삭제)를 하게 된다.
- 메모리 구조
Method
: Class Loader 가 적재한 클래스 정보(인퍼테이스 포함), Static 변수(기본형이 아닌 변수의 인스턴스는 Heap에 저장), JVM이 시작할 때 올라가는 정보들을 가지고 있는다.모든 Thread
가 공유한다.Stack
: Thread마다 동적으로 생성된 영역. ex) 객체의 주소=참조변수 Person P = new Person(“aaa”), Primitive TypePC Register
: Thread가 어떤 부분을 어떤 명령어로 수행할 지. 즉 실행하는 주소를 저장한다. cf. cpu register counter: 다음에 실행될 주소를 저장Native Method Stack
: Java 이외의 언어로 작성된 네이티브 코드가 올라가는 메모리 영역Heap
: 구조는 이미지를 참조. new 연산자로 생성된 객체를 저장.eden
: 새로 생성되는 객체servival0~1
: eden 영역이 가득차고 young(minor) GC가 반복되어 살아남은 객체old generation
: young generation의 servival0~1에서 특정 조건(age)이 충족된 객체가 상주
GC 참고
- 동작
새로 생성(new 연산자)되는 객체가 eden에 상주 -> eden full 되면
mark & sweep 과정으로 servical0 에 옮겨지며, servival 0이 가득차면 1로 1이 가득차면 0으로 이동하며 상주하게 되며 age가 증가한다.
(young generation 영역에서 발생하는 gc를 youn(minor) gc라고 한다.)
이 때, servival x 에서 일정 age 이상인 경우에 old generation 옮겨지는데 old generation 영역이 가득차게되면 old(major) GC가 발생한다.
- 종류
- serial GC: GC용 쓰레드 1개, 싱글 CPU에서 사용 -> Stop the world 결국 발생
- Parallel GC: Java 8의 Default GC. GC용 쓰레드가 따로 존재 -> Stop the world 결국 발생
- CMS GC: Concurrent Mark Sweep. GC용 쓰레드가 계속 백그라운드에서 작업. 멈추지 않는 장점. cpu 부하. 중간중간 메모리를 제거하므로 파편화 -> 압축기능 없음
- G1 GC: 메모리를 기존처럼 연속된 사이즈로 나누지 않고, Region 단위로 구분하여 탐색하고 정리 ex) eden 영역 여러개 -> Region을 정리할 때 참조되는 객체는 다른 Region으로 옮김
JDK와 JRE의 차이
- JRE(Java Runtime Environment)
- 이미 개발된
프로그램을 실행
하고자 할 때 필요한 자바 실행 환경 - JVM + 표준 클래스 라이브러리
- 이미 개발된
- JDK(Java Development Kit)
- Java SE(Standard Edition)의 구현체
- JVM과 Java 프로그램 개발에 필수적인 도구와 라이브러리 API를 정의함.
- Java 프로그램에 개발에 필요한 JVM, 라이브러리 API, 컴파일러 및 개발 도구가 포함
- JRE + 개발에 필요한 도구
- Java SE(Standard Edition)의 구현체