자바 개발 전 C/C++를 사용할때: 각 하드웨어에 맞는 소스 코드를 여러개 작성해야되는 번거로움이 발생함(같은 기능의 소스코드인데도 달라야됨..)
자바 개발 후: 각 OS에 맞는 JVM만 있으면, 같은 기능을 구현한 소스코드가 하나만 있어도 OS 상관없이 사용할 수 있음
→ 자바는 WORA(Write Once Run Anywhere)를 구현하기 위해 자바(정확히는 컴파일된 바이트코드)를 OS에 독립적으로 두고 대신에 OS별로 나눠진 JVM(자바 가상 머신)을 사용해서, 하나의 바이트코드를 수정없이 여러 OS의 JVM이 실행시켜줌
→ 바이트 코드는 jvm이 이해할 수 있는 중간 코드임
사진을 보면 자바에만 JVM이 존재하는걸 볼 수 있는데, 그렇다면 자바 코드 실행 과정을 보면서 JVM이 무엇이고 C와 다르게 자바가 OS에 독립적일 수 이유가 JVM 때문인지도 알아보자
.java
)를 작성함.class
)로 번역해줌. 참고로 이 바이트코드는 아직 jvm이 읽을 수 없는 코드임JIT
등도 이에 해당된다는 점에 미루어, JVM 명세서에는 없지만 JVM 아키텍처를 설명할때 존재하는 기술 및 알고리즘이 있다는 사실을 인지하자.런타임 vs 컴파일 타임
- 컴파일 타임: 이때 발생하는 에러로는 문법 에러, 타입 체크 에러가 대표적인데, 런타임이 되기 전에 컴파일 오류가 발생해 런타임으로 가지 못함(실행되지 않음)
- 런타임: 쉽게 말해서 프로그램이 실행될 때를 의미. 대표적으로 exception이 있는데 이건 컴파일에서 잡지 못하고 런타임중에 조건을 만족했을때만 발생함
Class<?> myClass=Class.forName("com.example.MyClass");
클래스 로더의 특징
1. 계층 구조: 위의 사진처럼 클래스 로더끼리 부모-자식 계층 구조로 되어있음. 최상위 클래스 로더는 부트스트랩 클래스 로더임
2. 위임 모델: 클래스를 로드해야될때 먼저 상위 클래스 로더로 쭉 올라가(위임하여) 상위 클래스 로더에 있다면 해당 클래스를 사용하고, 없다면 다시 하위 클래스 로더로 쭉 내려오면서 맞는 클래스를 찾아 로드함
3. 가시성(visibility) 제한: 위임 모델에 의해 하위 클래스 로더는 상위 클래스 로더의 클래스를 찾을 수 있으나 그 반대는 안됨
4. 언로드(unload) 불가: 한번이라도 로드된 클래스는 jvm이 종료될때까지 메모리에 남아있어 중간에 임의로 메모리에서 해제할 수 없음. 다만 클래스 로더 자체를 삭제하는 방법을 쓸 수 있음
5. 네임스페이스(namespace): 각 클래스 로더는 로드된 클래스를 보관하는 네임스페이스가 있어서, 어떤 클래스를 로드할때 이 네임스페이스로 이미 로드된 클래스인지를 판별할 수 있음
6. 유일성 원칙: 하위 클래스로더가 상위 클래스 로더에서 로드한 클래스를 다시 로드하지 않아야 함(안그럼 동일한 클래스가 여러개 생기는 문제 발생함)
→ 클래스 로더가 클래스 로드를 요청받으면 클래스 로더 캐시→ 상위 클래스 로더로 쭉 위임→하위 클래스 로더로 내려오면서 해당 클래스를 찾는데 이미 로드된 클래스인지 판별하고 아니라면 파일 시스템에서 해당 클래스를 찾아서 로드함
클래스 로더 기본 종류
1. bootstrap class loader: jvm 기동시 생성되고 자바 자체의 클래스 로더와 Object,util,Class 클래스 등 기본 자바 api를 로드함
2. extension class loader: 기본 자바 api를 제외한 확장 클래스들을 로드함
3. system class loader: 애플리케이션의 클래스를 로드하는데 사용자가 지정한 $CLASSPATH
내의 클래스, jar에 속한 클래스를 로드함. 즉 개발자가 만든 .class 확장자 파일을 로드함
클래스 로더가 아직 로드되지 않은 클래스들을 로드하는 과정
로딩
1. loading: 클래스 로더가 해당 클래스 파일을 찾아서 jvm의 메모리에 로드함
classNotFountException
이 발생함링킹(Linking)
2. verifying(검증): 클래스 로드 전 과정 중에서 가장 복잡하고 시간이 많이 걸리는 과정으로, 읽어들인 클래스가 자바 언어 명세 및 jvm에 명시된대로 구성되어 있는지 검사함
3. preparing(준비): 클래스가 필요로 하는(필드/메소드/인터페이스) 메모리를 할당함.
4. resolving(분석): 클래스의 상수 풀 내 모든 심볼릭 레퍼런스를 다이렉트 레퍼런스로 변경함
초기화
5. initializing(초기화): 클래스 변수들을 적절한 값으로 초기화함(이때 static 필드가 설정된 값으로 초기화됨)
pc 레지스터
네이티브 메소드 스택(native method stack)
jvm 스택
힙
메소드 영역(method area)
static final
) 뿐만 아니라 메소드와 필드에 대한 모든 레퍼런스까지 담고 있는 테이블로, 어떤 메서드나 필드를 참조할때 jvm은 런타임 상수 풀을 통해 해당 메소드나 필드의 실제 메모리상 주소를 찾아서 참조함 해당 부분을 JVM에 포함하는 글, 포함하지 않는 글이 존재함.
Thread
의 currentThread()
임해당 부분을 JVM에 포함하는 글, 포함하지 않는 글이 존재함.