728x90
DevOps 쪽이 Java로 많이 이루어져있다보니 자바 동작원리나 언어를 다시 좀 봐야겠다는 생각이 들었다.
JVM
- OS에 종속받지 않고 CPU가 Java를 인식, 실행할 수 있게 하는 가상 컴퓨터
- java 소스코드는 JVM을 통해 어떤 OS든 상관없이 실행할 수 있도록 해줌.
- java 소스코드(.java) → (JVM이 이해할 수 있는) 자바 바이트코드로 변환(.class) → 이진코드(기계어)로 컴파일
- java코드 → (자바 컴파일러=javac.exe) → .class → (JIT) → 기계어
- JIT (just-in-time compiler)
- 프로그램을 실제 실행하는 시점에 기계어로 번역하는 컴파일러
- 인터프리터 방식 단점을 보완하기 위해 도입. 인터프리터 방식으로 실행하다가 적절한 시점에 바이트 코드 전체를 컴파일하여 기계어로 변경 → 기계어로 직접 실행
- 기계어로 컴파일된 코드는 캐시에 보관된다 → 자주 실행되는 코드들은 JIT 컴파일, 한번 실행되는 코드들은 인터프리팅
javac.exe : .class 파일 생성 (자바 바이트 코드)
java.exe : JVM을 구동시키기 위한 프로그램. .class 파일을 실행시킬 수 있음
이미지 출처: https://doozi0316.tistory.com/entry/1주차-JVM은-무엇이며-자바-코드는-어떻게-실행하는-것인가
Run time data area
프로그램을 수행하기 위해 OS에서 할당받은 메모리 공간
이미지 출처: https://d2.naver.com/helloworld/1230
Thread → PC register
- thread에 생성되는 공간. 쓰레드가 어떤 부분을 어떤 명령으로 실행햐할 지에 대한 기록 저장
Thread → JVM stack
- 변수나 임시데이터(지역변수 등등), 스레드나 메소드의 정보 저장
- 메소드 호출시 필요한 데이터 저장
Thread → Native method stack
- java가 아닌 다른 언어(C++ 등) 코드를 java native interface를 통해 호출하여 수행하기 위한 스택
Method area
- 모든 스레드가 공유하는 영역으로 JVM이 시작될 때 생성
- JVM이 읽어 들인 정보( 각각의 클래스와 인터페이스에 대한 런타임 상수 풀, 필드와 메서드 정보, static 변수, 메서드의 바이트코드 등)를 보관.
- JVM 벤더마다 다양한 형태로 구현 가능
- 오라클 핫스팟 JVM(HotSpot JVM)에서는 흔히 Permanent Area, 혹은 Permanent Generation(PermGen)이라고 불린다.
- 메서드 영역에 대한 가비지 컬렉션은 JVM 벤더의 선택 사항
Runtime constant pool
- 클래스 파일 포맷에서 constant_pol 테이블에 해당하는 영역
- 메서드 영역에 포함되는 영역이긴 하지만 JVM 동작에서 가장 핵심적인 역할을 수행하는 곳이라 따로 명시
- 각 클래스와 인터페이스의 상수뿐만 아니라 메서드와 필드에 대한 모든 레퍼런스까지 담고 있는 테이블
- 어떤 메서드나 필드를 참조할 때 JVM은 런타임 상수 풀을 통해 해당 메서드나 필드의 실제 메모리상 주소를 찾아서 참조
Heap
- 인스턴스 또는 객체를 저장하는 공간으로 가비지 컬렉션 대상. JVM 성능 등의 이슈에서 가장 많이 언급되는 공간.
- 힙 구성 방식이나 가비지 컬렉션 방법 등의 JVM 벤더의 재량
이미지 출처: https://doozi0316.tistory.com/entry/1주차-JVM은-무엇이며-자바-코드는-어떻게-실행하는-것인가
- 객체를 저장하는 가상메모리 공간. new 연산자로 생성되는 개체와 배열을 저장
- 세 부분으로 나눠져 있음
- New/young, old 영역은 가비지 콜렉터에 의해 관리된다.
- 처음 생성된 객체는 Eden에 위치 → MinorGC에 의해 사용안되는 객체 제거→ 살아남은 객체는 survivor1,2을 왔다갔다 이동하게 됨 → 반복되는minorGC에 오래 살아남은 객체들은 Old gen으로 이동. (young gen 영역이 가득 찼을 경우에도 이동)
GC(가비지 콜렉터)
힙 영역에서 발생
- 역할
- 메모리 할당
- 사용중인 메모리 인식
- 사용하지 않는 메모리 인식
- GC방식
- 시리얼 콜렉터
- 병력 콜렉터
- 병렬 콤팩팅 콜렉터
- CMS 콜렉터
- G1 콜렉터
- 종류
- 마이너 GC: young 영역에서 발생
- 메이저 GC(full GC): old, perm 영역에서 발생
- Mark-sweap-compact:
- sweap 과정에서 발생한 scattered holes를 메우기?위해 재구성 과정(compact) 과정을 거침
- compact 과정에서 GC를 수행하는 스레드를 제외한 나머지 스레드가 정지
- full GC가 자주 일어나고 수행시간이 길 경우 WAS 응답시간에 영향
- 두 가지 GC가 어떻게 상호작용 하느냐에 따라 GC 방식에 차이가 나고 성능에 영향을 준다.
- GC가 발생하거나 객체가 각 영역에서 다른 영역으로 이동할 떄 애플리케이션의 병목이 발생하면서 성능에 영향을 주게 된다.
- 핫스팟 JVM에서는 스레드 로컬 할당 버퍼(TLABs)를 사용. 이를 통해 각 스레드별 메모리 버퍼를 사용하면 다른 스레드에 영향을 주지 않는 메모리 할당 작업이 가능
- Full GC를 수행하는 시점에는 응답시간이 느려진다. (→ 카프카 등에서 이로 인해 응답시간이 느려져 주키퍼와의 통신이 끊어질 수 있으니 응답대기초를 얼만큼 해라 그런 조언이 있었다.) 강제로 gc하는 코드를 넣었을 때 응답속도가 매우 느려지는 테스트를 많이 볼 수 있음.
- GC튜닝을 통해 FULL GC의 횟수 또는 수행 시간 조절 가능
- young 영역 크기 조절: old 영역으로 넘어가는 객체 수를 줄이면 Full GC 빈도 줄일 수 있음
- old 영역 크기 조절:
- 크기 줄이면 Full GC 수행시간 줄어듦, but 수행 자주 일어나거나 OOM 일어날 수 있음
- 크기 늘리면 Full GC 발생빈도 줄일 수 있지만 수행시간 늘어남
JDK(java development kit)
- java를 사용하기 위해 필요한 모든 기능을 갖춘 java용 SDK
- JRE 포함
- 프로그램을 생성, 실행, 컴파일할 수 있음
JRE(java runtime environment)
- JVM+자바 클래스 라이브러리 등으로 구성
- 컴파일된 JAVA 프로그램을 실행하는데 필요한 패키지
참조
- https://d2.naver.com/helloworld/1230
- https://doozi0316.tistory.com/entry/1주차-JVM은-무엇이며-자바-코드는-어떻게-실행하는-것인가
- https://velog.io/@jsj3282/17.-도대체-GC는-언제-발생할까
- https://dheldh77.tistory.com/entry/자바-가비지-컬렉션GC-Garbage-Collection
언어 얘기가 나왔는데 이것저것 찾다 각 언어 서버별 I/O 처리 속도 비교하는 재밌는 글.
반응형