Optimizing Java를 읽고 정리한 게시글 입니다.
1. 인터프리팅과 클래스 로딩
- JVM이란 스택 기반의 해석 머신입니다. ( 일부 결과를 실행 스택에 보관하며 맨 위의 값을 가져와 계산)
- 해석을 진행할때는 평가스택을 이용하여 중간값을 담아두는 방식을 채택합니다. 이는 가장 마지막 실행된 명령어와 독립적으로 프로그램을 구성하는 옵저버를 하나씩 순서대로 처리함을 의미합니다.
- " 자바 가상 환경 구성 → 스택 머신 초기화 → (유저가 작성한) 클래스 파일 실행 " 을 순서로 진행합니다.
- 클래스 로딩 매커니즘은 쉽게 아래와 같습니다.
- 자바 프로세서 초기화 → 클래스 로더 차례로 작동
- 클래스 로더 순서 : 부트스트랩 클래스(java.lang.Object, Class, ClassLoader) → 자바 런타임 코어 클래스 → 확장 클래스 로더 → 어플리케이션 클래스로더 → 유저 클래스 로드
- 자바 프로세서 초기화 → 클래스 로더 차례로 작동
2. 바이트코드 실행
자바 컴파일러 (javac) 로 컴파일을 하면 .class 파일로 변환이 이루어 집니다.( 이는 쉽게 디코딩 가능 )
바이트 코드는 IR( intermediate repersentation) (중간 표현형 ) :컴퓨터 아키텍쳐에 구애 받지 않는 언어 로써 JVM위에서 실행하도록 사용됩니다.
JVM 지원 플랫폼 위에서는 실행 가능 ( 추상화 )
3. 핫스팟 입문
자바는 핫스팟을 통해서 프로그램의 런타임 동작을 분석하고 성능에 가장 유리한 방향으로 영리한 최적화를 적용하는 가상 머신입니다.
핫스팟 VM의 목표는 개발자가 억지로 VM 틀에 맞게 프로그램을 욱여넣는 대신, 자연스럽게 자바 코드를 작성하고 바람직한 설계 원리를 따르게 합니다.
3.1 JIT 컴파일이란
자바 프로그램은 바이트코드 인터프리터가 가상화한 스택 머신에서 명령어를 실행하는 것으로 시작합니다.
핫스팟은 프로그램 단위(메서드와 루프)를 인터프리티드 바이트코드에서 네이티브 코드로 컴파일 하는것을 의미합니다.
JIT ( Just in time ) 그때그때 하는 컴파일이라는 의미로 아래와 같은 역할을 수행할 때 쓰는 기법입니다.
핫스팟은 인터프리티드 모드로 실행하는 동안 애플리케이션을 모니터링하면서 가장 자주 실행되는 코드 파트를 발견하여 JIT컴파일을 수행합니다. 이렇게 분석을 하는 동안 미리 프로그래밍한 추적 정보가 취합되면서 더 정교하게 최적화 가능합니다.
특정 메서드가 어느 한계치를 넘어가면 프로파일러가 특정 코드 섹션을 컴파일/최적화 합니다.
이점
컴파일러의 해석 단계에서 수집된 추적 정보를 근거로 최적화 진행이 가능해 집니다. ( 실행속도가 증가합니다 )
자바는 PGO( 프로필 기반 최적화 ) ( 컴파일러가 프로그램 실행의 런타임 프로필을 사용하여 인라인 처리와 코드 레이아웃에 관해 최적의 선택 ) 를 응용하는 환경에서는 AOT 플랫폼 (ahead-of-time compile)에서 불가능한 방식으로 런타임 정보를 활용할 여지가 있으므로 동적 인라이닝 또는 가상 호출 등으로 성능 개선이 가능하다.
JIT vs AOT
JIT 컴파일러가 바이트코드를 런타임에 기계어로 바꾼다면
AOT는 실행 전에 바이트코드를 기계어로 바꾸는 컴파일러 입니다.
따라서 JIT 와 AOT는 컴파일의 시점을 차이점 을 가지고 있습니다.
AOT 컴파일 방식은 실행 전에 모두 기계어로 변환되기 때문에 JIT 컴파일러가 런타임에 컴파일 하기 때문에 발생하는 성능 이슈가 생기지 않고 거의 네이티브의 성능을 낼 수 있게 됩니다.
AOT 컴파일러가 JIT 컴파일러의 정반대의 원리기 때문에 JIT 컴파일러의 장점은 AOT 컴파일러의 단점이되는 경우가 있습니다.
AOT 컴파일러를 사용하면 실행 전에 전체 파일을 빌드해야 하기 때문에 빌드 속도가 느려지고 설치할 때도 JIT 컴파일러를 사용하는 경우 바이트 코드만 받으면 되는 반면 AOT 컴파일러를 사용하면 기계어로 번역하는 작업까지 포함되기 때문에 느리다는 단점이 있습니다.
그리고 JIT 컴파일러의 장점이었던 Hot Reload 기능도 사용할 수 없습니다.
아래는 참고하면 좋을 링크입니다.
4. JVM 메모리 관리
자바는 가비지 수집이라는 프로세스를 이용해 힙 메모리를 자동 관리하는 방식으로 해결합니다.
즉, 불필요한 메모리를 회수하거나 재사용하는 불확정적 프로세스를 JVM 에서 관리해줍니다. 줄여서 GC (가비지 컬렉터)라고합니다.
GC 실행시 모든 애플리케이션 중단 ( stop the world )이 발생합니다. 즉 모든 스레드의 동작이 종료합니다.
5. 스레딩과 자바 메모리 모델 (JMM )
JMM이란?
- 서로 다른 실행 스레드가 객체 안에 변경되는 값을 어떻게 바라보는지를 기술한 공식 메모리 모델입니다.
해당 내용을 파악하기 위해서는 아래 원칙을 알아야합니다.
자바 멀티스레드 3가지 기본 설계 원칙
- 자바 프로세스의 모든 스레드는 가비지가 수집되는 하나의 공용 힙을 가집니다.
- 한 스레드가 생성한 객체는 그 객체를 참조하는 다른 스레드가 액세스할 수 있습니다.
- 기본적으로 객체는 변경가능합니다. 즉, 객체 필드에 할당된 값은 프로그래머가 애써 final 키워드로 불변을 표시하지 않는 한 바뀔 수 있습니다.
서로 다른 스레드가 같은 객체를 참조하는 상황이라면 상호 배타적락을 이용하여 객체의 손상을 막는 방식을 채택합니다.
6. JVM 구현체 종류
- OpenJDK
- 자바 기준 구현체(reference implementation)를 제공하는 특별한 오픈소스 프로젝트
- Oracle
- 가장 잘알려진 구현체
- 오라클 상용 라이선스
- Zulu
- Azul 시스템이 제작한 무료 OpenJDK
- IcedTea
- Zing
- J9
- Avian
- Android
- 최초의 안드로이드는 여러가지 자바 클래스 라이브러리 구현체와 교차 컴파일러를 사용했음.
JVM 라이선스
대부분 오픈소스지만 ..
오라클 자바 ( 자바 9 이후 ) 라이선스는 확인해야합니다.
오라클 JDK & OpenJDK는 라이선스 외에는 동일하다
그러나 주의해야할 점이 있습니다.
- 회사 밖으로 오라클 바이너리를(ex. 도커 이미지) 재배포 행위는 허용되지 않습니다.
- 사전 동의(서비스 지원 계약) 없이 오라클 바이너리를 함부로 패치하면 안됩니다.
7. JVM 모니터링과 툴링
실행 중인 애플리케이션을 인스트루먼테이션, 모니터링 관측하는 다양한 기술이 있습니다.
- 자바 관리 확장 ( JMX )
- JVM 과 그 위의 애플리 케이션을 제어하고 모니터링하는 강력한 범용 툴입니다.
- 이는 JVM을 관리하는 기본 수단입니다.
- 자바 에이전트
- 자바 언어로 작성된 툴 컴포넌트 :: 메서드 바이트 코드를 조작하는 도구입니다.
- 에어전트 jar 파일에서 메니페스트는 필수입니다.
- JVM 틀 인터페이스 (JVMTI
약간 MBTI같기도하공,,ㅎㅎ)- JVM의 네이티브 인터페이스라고 합니다.
- JVM 이벤트를 모니터링하며 알림을 받을 수 있도록 만든 통신 인터페이스
- 일반적으로는 사용을 안하는 것이 좋습니다. (위험합니다.)
- 서비서빌리티 에이전트 ( SA )
- 자바 객체, 핫스팟 자료 구조 모두 표출 가능한 APi와 툴을 모아놓은 것입니다.
- JVM에서 코드를 실행할 필요없습니다.
7.1 VisualVM
플랫폼 기반 시각화 툴입니다
쓰면 좋을듯 싶습니다.
'TIL' 카테고리의 다른 글
Github Action 하나로 자동 배포 WorkFlow 만들기 ( Spring Boot ) (0) | 2023.03.31 |
---|---|
가비아 도메인 Tistory 블로그에 연결하기 ( 비공개연결 해결하는법) (0) | 2023.03.21 |
[네트워크 1장] DNS 서버 (0) | 2022.09.27 |
[운영체제 14~15강] 프로세스 메모리 할당 그리고 파일 상태 (2) | 2022.09.20 |
[운영체제 11장] CPU 스케쥴링 (0) | 2022.09.18 |