그 이름도 지겨운 JVM!!!
JVM이란 자바 가상 머신이다. 영어로는 JVM : Java Virtual Machine이다.
JVM이 대체 무엇인지? JVM의 역할은 무엇인지 알아보자
JVM의 정의
JVM을 2가지로 정의할 수 있는데 첫번째는 기술적 정의이다.
JVM은 코드를 실행하고 해당 코드에 대해 런타임 환경을
제공하는 소프트웨어 프로그램에 대한 사양(Specification)이다.
두번째는 일반적 정의이다.
JVM은 자바 프로그램을 실행하는 방법이다. JVM의 설정을 구성한 설정사항에 따라
실행 중에 프로그램 리소스를 관리한다.
JVM의 역할?
1. OS에 구애받지 않는 실행
사용자가 작성한 자바 코드는 자바 컴파일러에 의해 자바 바이트 코드로 컴파일되고
JVM은 이 자바 바이트 코드를 사용자의 컴퓨터가 어떤 OS를 사용하든 상관없이 돌아가게끔 만들어준다.
즉, 원래 프로그램은 Windows에서 개발되었다면 Mac이나 Linux에서는 구동할 수 없다.
하지만 자바는 JVM만 실행 환경에 맞춰 준비해 놓으면 어떤 OS를 사용하든지 상관없이 구동할 수 있다는 뜻이다.
한 번 작성해 어디에서나 실행한다 라는 것으로 유명한 것이 바로 JVM의 원칙이다.
Window에서 개발되었더라도 Mac에 맞추어 JVM을 준비만 해두면 실행이 가능하다는 것이다.
참고로 JVM은 이름에 자바가 들어가기 때문에 자바에만 적용될 수 있는 것이라고 생각하기 쉽지만,
사실 코틀린 등 다른 언어도 컴파일 할 수 있다. 물론 자바가 가장 기본이다.
생각해보면 컴퓨터 OS가 1, 2, 3, 4, 5 총 5개가 존재한다고 했을 때
각 OS마다 새로 컴파일을 해야한다고 하면 생각만해도 끔찍하다.
이러한 불편을 줄여주는 JVM이라는 녀석 아주 마음에든다.
쉽게말해 5명의 사람이 모여 대화를 하는데 각자 언어가 다르다고 해서
한 사람 한 사람 모두에게 다 통역관을 붙일 수는 없다.
그럴때 5개국어가 가능한 사람이 있다면?
그 사람 혼자 다 알아듣고 다 통역하면 훨씬 일처리가 수월하다.
그런 통역을 해주는 중심역할이 JVM이라고 생각한다.
우리가 자바로 코딩을 하고 컴파일을 때리면 기계어로 변환되지 않고 바이트코드라는 것이 생성된다.
바이트코드는 사람과 기계 그 사이 어딘가 라고 생각하면 된다.
사람의 언어도 아니고 그렇다고 기계의 언어도 아닌 그 중간지점이다.
자바 컴파일 뿅! ——→ .class 생성 ! 짜잔! ←—- 이녀석이 바이트 코드이다.
이 클래스 파일을 가져다주면 JVM이 받아서 그때 그때 각 OS에서 컴파일을 해주는 것이다.
파파고라고 보면된다.
쏼라쏼라 못알아듣겠어 외계어같아 알아듣게 번역해서 알려줘~ 파파고(JVM)~ 네 통역하겠습니다 (컴파일) ~
어떤 언어든 통역해서 알려주는 파파고! = 어떤 OS에서든 기계어로 컴파일해주는 JVM
파파고(언어통역) = JVM(기계어로 컴파일)
그때그때 마다 컴파일 즉 통번역해주는 이런 행위를 JIT 라고 한다.
JUST IN TIME = JIT
JIT컴파일!!
이쯤에서 다시 외쳐보자
Write Once Run Anywhere! 한번 작성해서 어디서든 동작한다!
WORA !
2. 메모리 관리
JVM은 가비지 컬렉터(Garbage Collector)를 통해 자동으로 동적할당된 메모리(Heap) 영역의 쓰지 않는 메모리를 탐지하여 해제하는 기능이 있다. 이를 통해 한정된 메모리를 효율적으로 사용할 수 있다.
가비지 컬렉터란?
자바 이전에는 프로그래머가 모든 프로그램 메모리를 관리했었다. 자바에서는 JVM이 프로그램 메모리를 관리한다. JVM은 가비지 컬렉터란 프로세스를 통해 메모리를 관리하며, 이 가비지 컬렉터는 자바 프로그램에서 사용되지 않는 메모리를 지속적으로 찾아내서 제거한다. 가비지 컬렉터는 실행 중인 JVM 내부에서 일어난다.
Stack 그리고 Heap이란?
JVM의 Heap 영역은 동적으로 할당된 메모리의 영역이다.
모든 Object 타입의 데이터가 할당, Heap 영역의 Object를 가리키는 참조 변수가 Stack에 할당된다.
코드 예시를 보면
package HellJavaStudy;
public class Main {
public static void main(String[] args) {
int num1 = 10;
int num2 = 5;
int sum = num1 + num2;
String name= "던";
System.out.println(sum);
System.out.println(name);
}
}
위 코드를 실행할 때 Stack과 Heap으로 나눠서 설명하면
위에서 부터 순차적으로 실행되기 때문에
Stack은
- num1=10
- num2=5
- sum=15
- name
1~4 순서로 차곡차곡 쌓이게 된다
String은 객체이기 때문에
Heap영역에 생기게되고 던이라는 객체를 참조하는 변수가 Stack에 저장하게 된다.
이후에 이 메서드가 실행이 종료되면 팝되면서 Stack영역 데이터는 모두 날라가게 되고
Heap영역에 객체타입의 데이터만 남게되는데 이런 객체를
Unreachable Object라고 하고 이런 객체가 가비지컬렉터의 대상이 된다.
가바지 컬렉터 과정을 적어보자면
- 가비지 컬렉터가 스택의 모든 변수를 스캔하면서 각각 어떤 객체를 참조하고 있는지 찾아서 마킹한다.
- Reachable Object가 참조하고 있는 객체도 찾아서 마킹한다.
- 마킹되지 않은 객체를 Heap에서 제거한다.
names라는 객체가 스택에 있다고 가정해보자
Heap영역에 List형태로 012가 존재하는데
0은 String 미스터코
1은 String 뚱이
2는 String 큰곰
이라고 했을 때
각자 0부터 2까지 마킹이 되는데
마킹되지 않은 던 이라는 것이 있다면
Heap은 노마킹 대상이니까 찾아서 제거해버린다.
이렇게 지워버리는 것을 Sweep라고 한다.
그래서 이런 과정을 Mark and Sweep라고 부른다.
가비지컬렉터가 일어나는 순간은 언제일까?
순서대로 알아보자
- 대부분의 객체는 금방 접근 불가능한 상태(Unreachable)가 된다.
- 오래된 객체에서 새로운 객체로의 참조는 아주 적게 존재한다.
이 가설의 장점을 살리기 위해 JVM의 Heap 영역에는 두 개의 영역이 존재한다.
- Young 영역(Young Generation)
- Young영역에 대한 GC를 Minor GC라고 부른다.
- 영역으로는 Eden, Survivor0, Survival1 이 존재한다.
- 이렇게 반복되면서 특정 Age값을 넘어서면 Old영역으로 옮겨가게 되는데 이러한 것을 Promotion이라고 한다.
- 쉽게말해 에덴에서 0으로 가고 0에서 1로 가고 1에서 다시 0으로가고 0에서 다시 1로 가고
- 이후에 또 0번이 포화상태가 되면 Survivor1로 옮겨가게되고 이동한 객체는 Age값이 하나씩 증가하게된다.
- Old 영역(Old Generation)
- Young 영역에서 Reachable 상태를 유지하여 살아남은 객체가 복사되는 영역이다.
- 복사되는 과정에서 대부분 Young 영역보다 크게 할당되며, 크기가 큰 만큼 가비지는 적게 발생한다.
- Old 영역에 대한 GC를 Major GC 또는 Full GC라고 부른다.
컴파일러란?
컴파일러에 앞서 컴파일 이라는 단어의 뜻 자체가 무엇인지 알고 갈 필요가 있다.
Compile(컴파일)이란?
사람이 작성한 소스코드(프로그래밍 언어)를 컴퓨터가 이해할 수 있게 기계어로 해석하는 과정(프로그래밍 언어-> 기계어)
즉 사람끼리 이해 할 수 있는 프로그래밍 언어를 컴퓨터에서 인식하지 못하기 때문에 기계가 알아들을 수 있도록 바꿔주는 과정이다.
컴파일러는?
특정 프로그래밍 언어로 쓰여 있는 문서를 다른 프로그래밍 언어 혹은 컴퓨터 언어로 옮기는, 일종의 번역 프로그램이다.
비주얼, 터보, 볼랜드 등 언어에 따라 다양한 컴파일러 종류가 존재한다고 한다.
보통 high-level 프로그래밍 언어를 실행 프로그램으로 만들기 위한 lower level언어
ex)어셈블리 언어, object 코드 등으로 바꾸는데 사용된다.
비주얼이 뭘까?
컴퓨팅에서 비주얼 프로그래밍 언어(visual programming language, VPL) 또는 시각 프로그래밍 언어는 사용자가 텍스트로 지정하는 대신 그래픽적으로 프로그램 요소를 조작하여 프로그램을 개발할 수 있게 하는 모든 종류의 프로그래밍 언어를 일컫는다.
터보가 뭘까?
터보 C(Turbo C)는 C 프로그래밍 언어를 위한 볼랜드 통합 개발 환경과 컴파일러였다. 1987년에 처음 선을 보였으며 통합 개발 환경, 작은 크기, 극히 빠른 컴파일 속도, 상세한 설명서, 낮은 가격 등으로 주목을 받았다. 1990년 5월, 볼랜드는 터보 C를 터보 C++로 대체하였다. 2006년, 볼랜드는 터보 익스플로러를 다시 소개하였다.
볼랜드가 뭘까?
C++ Builder, Delphi 등으로 유명했던 미국 텍사스 주의 소프트웨어 기업. 현재는 Micro Focus에게 인수되어 볼랜드라는 명칭은 사라졌다.
여기서 잠깐 컴파일을 할 때 자주 나오는 원시코드와 목적코드가 뭘까?
원래의 문서를 '소스 코드' 혹은 원시코드라고 부른다.
출력된 문서를 '목적 코드' 라고 부른다.
원시코드? 목적코드? 이게 무엇일까?
프로그램이 Compiler에 의해 compile 되기 '이전'과 '이후'라고 할 수 있다.
원시코드란(Source Code)?
프로그래밍 언어로 작성된 텍스트 원시코드로 작성된 파일은 컴파일러에 의해 파일이 컴파일 된다.
목적코드란(Object Code)란?
목적코드 또는 목적파일이라고 불리는데 소스코드 컴파일의 결과물, 즉 컴파일 된 파일을 말한다.
원시코드 -> 컴파일러 -> 목적코드
이 순서로 볼 때 사람들끼리 알아들을 수 있는 프로그래밍 언어 윈시코드를 컴파일해서 컴퓨터 즉 기계가 알아들을 수 있는
기계어로 바꾸게 되고 변경된 코드를 목적코드라고 할 수 있다.
추천 및 참고자료 :
- tescoble - JVM에 관하여 - ClassLoader
- IF(kakao) - JVM warm up ⇒ 링크
- [10분 테코톡] 🎅무민의 JVM Stack & Heap
- Back to the Essence - Java 컴파일에서 실행까지 - (1)
- [이론] 컴파일러, 인터프리터, JIT
- JIT 컴파일 - 위키피디아
- **컴파일러, 인터프리터
- [10분 테코톡] **던의 JVM의 Garbage Collector
'BackEnd' 카테고리의 다른 글
SQL 데이터베이스에 대해 제대로 알자(1) - 데이터베이스란? (0) | 2023.03.08 |
---|---|
접근제어자(Access Modifier) 무조건 이해하기 (0) | 2023.02.13 |
PostgreSQL이란? (0) | 2023.01.30 |
ACID란? (0) | 2023.01.30 |
프로시저(Procedure)란 대체 무엇일까? (0) | 2023.01.25 |