[Java] 더 자바, 코드를 조작하는 다양한 방법 강의 정리
“더 자바, 코드를 조작하는 다양한 방법” 강의 정리
1. 자바, JVM, JDK, JRE
1-1. JVM
- Java Virtual Machine
- 클래스를 읽고 메모리에 올려주고 실행.
- 자바 가상 머신으로 자바 바이트 코드(.class파일)를 OS에 특화된 코드로 변환(인터프리터와 JIT 컴파일러)하여 실행
- OS에 의존적이기 때문에 특정 플랫폼에 종속적.
1-2. JRE
- 자바 애플리케이션을 실행할 수 있도록 구성된 배포판.
- JVM + 라이브러리
- 컴파일시에 사용되는 javac(java compiler)는 포함되지 않음
1-3. JDK
- 오라클 Java 11 부터는 JRE를 배포하지 않음
- JRE + 개발에 필요한 툴
- 소스 코드를 작성할 때 사용하는 자바 언어는 플랫폼에 독립적
1-4. Java
- 프로그래밍 언어
- JDK에 들어있는 자바 컴파일러(javac)를 사용해 바이트코드(.class 파일)로 컴파일 할 수 있다
2. JVM 구조
2-1. 클래스 로더 시스템
- 컴파일된 .class 에서 바이트 코드를 읽고 메모리에 저장 클래스 로더가 하는 일 3가지
- 로딩 : 클래스 읽어오는 과정
- 링크 : 레퍼런스를 연결하는 과정
- 초기화 : static 값들 초기화 및 변수에 할당
2-2. 메모리
5가지 영역
스택
, PC
, 네이티브 메소드 스택
은 특정 스레드 내에서만 공유 됨.
- 스택
- 쓰레드 마다 런타임 스택을 만들고, 그 안에 메서드 호출을
스택 프레임
이라 부르는 블럭으로 쌓는다. 쓰레드 종료하면 런타임 스택도 사라짐
- 쓰레드 마다 런타임 스택을 만들고, 그 안에 메서드 호출을
- PC
- Program Counter
- 쓰레드 마다 쓰레드 내
현재 실행할 스택 프레임을 가리키는 포인터
가 생성된다
- 네이티브 메소드 스택
- 쓰레드 마다 생성됨
native
키워드를 붙여놓고 C 또는 C++로 구현한 메서드가네이티브 메소드 선택
- 힙
- 객체 저장
- 공유 저장
- 메소드
- 클래스 수준의 정보 저장 : 클래스 이름, 부모 클래스 이름, 메소드 변수
- 공유 자원 : 다른 영역에서도 참조할 수 있는 정보
2-3. 실행 엔진
- 인터프리터
- 바이트 코드를 한줄 씩 실행
- JIT 컴파일러
- 인터프리터 효율을 높이기 위해, 인터프리터가 반복되는 코드를 발견하면 JIT 컴파일러로 반복되는 코드는 모두 네이티브 코드로 바꿔둔다. 그 다음부터 인터프리터는
네이티브 코드로 컴파일된 코드를 바로 사용
한다. - 바이트 코드를 네이티브 코드로 컴파일해줌
- 인터프리터 효율을 높이기 위해, 인터프리터가 반복되는 코드를 발견하면 JIT 컴파일러로 반복되는 코드는 모두 네이티브 코드로 바꿔둔다. 그 다음부터 인터프리터는
- GC
- Garbage Collector
- 더이상 참조되지 않는 객체를 모아서 정리한다.
2-4. 네이티브 메소드 인터페이스(JNI) & 네이티브 메소드 라이브러리
- 네이티브 메소드 라이브러리를 사용하기 위해서는 네이티브 메소드 인터페이스를 사용
- JNI
- 자바 애플리케이션에서 C, C++ ,어셈블리로 작성된 함수를 사용할 수 있는 방법 제공
- native 키워드를 사용해 호출
- 네이티브 메서드 라이브러리
3. 클래스 로더
로딩, 링크 초기화 순으로 진행됨
3-1. 로딩
- 클래스 로더가 .class 파일을 읽고 그 내용에 따라 적절한 바이너리 데이터를 만들고
메소드
영역에 클래스 정보 저장 - 메소드 영역에 저장하는 데이터
- FQCN
- 클래스 / 인터페이스 / enum
- 메서드와 변수
- 로딩이 끝나면 해당 클래스의 Class 객체를 생성하여
힙
영역에 저장
3-2. 링크
- Verify, Prepare, Resolve(optional) 세 단계로 나눠짐
- 검증 : .class 파일 형식이 유효한지 체크
- Preparation : 클래스 변수(static 변수)와 기본값에 필요한 메모리
- Resolve : 심볼릭 메모리 레퍼런스를 메소드 영역에 있는 실제 레퍼런스롤 교체한다
3-3. 초기화
리플렉션
- 리플랙션을 통해 클래스의 풀패키지 패스 문자열만으로 객체를 생성하고 파라미터를 전달하는 등의 동작이 가능하다.
- Spring의 DI는 리플랙션을 활용해 객체를 주입한다.
리플렉션 사용시 주의할 것
- 지나친 사용은 성능 이슈 야기. 반드시 필요한 경우에만 사용
- 컴파일 타임에 확인되지 않고
런타임
시에만 발생하는 문제를 만들 가능성 존재 - 접근 지시자 무시할 수 있음
스프링
- 의존성 주입 DI
- MVC 뷰에서 넘어온 데이터를 객체에 바인딩할 때