운영체제에 독립적이다.
객체 지향 언어이다.
자동 메모리 관리 (GC)
네트워크와 분산처리를 지원한다.
멀티쓰레드를 지원한다.
💡 자바 실행 과정
- 자바는 자바 코드(.java)를 자바 가상 머신(JVM)이 실행시킬 수 있는 자바 바이트 코드(.class)로 변환한다.
- 이후 자바 바이트 코드는 JVM의 자바 인터프리터를 이용해 운영체제, 하드웨어가 이해할 수 있는 2진 코드로 변환한 후 실행시킨다.
개발자가 자바 코드(.java)를 작성한다.
자바 컴파일러가 자바 코드를 JVM이 이해할 수 있는 바이트코드로 컴파일한다.
바이트 코드를 JVM의 클래스 로더에게 전달한다.
클래스 로더는 동적 로딩을 통해 필요한 클래스들을 로딩 및 링크하여 런타임 데이터 영역인 JVM 메모리에 올린다.
💡 JVM 동적 클래스 로딩
- 클래스 로더는 '.class" 바이트 코드를 읽어 class 객체를 생성하는 역할을 담당한다.
- 클래스 로딩은 세부적으로 로딩, 링크 초기화라는 3단계의 과정을 거친다.
- 로딩 : 클래스 파일을 바이트 코드로 읽어 메모리로 가져오는 과정
- 링크 : 읽어온 바이트 코드의 자바 규칙 검증과 클래스에 정의된 필드, 메소드, 인터페이스들을 나타내는 데이터 구조를 준비하며, 그 클래스가 참조하는 다른 클래스를 로딩하는 과정
- 초기화 : 슈퍼 클래스 및 정적 필드를 초기화하는 과정
실행 엔진은 JVM 메모리에 올라온 바이트 코드들을 명령어 단위로 하나씩 가져와서 실행한다.
💡 Java 인터프리터
- 바이트 코드 명령어를 하나씩 읽어서 해석하고 실행한다.
- 명령어 각각의 실행은 빠르나, 전체적인 실행 속도가 느리다.
💡 JIT 컴파일러
- Just-In-Time 컴파일러
- 바이트코드를 CPU로 직접 보낼 수 있는 바이너리 코드로 바꾸는 역할
- 성능 최적화를 위해 애플리케이션 런타임을 향상시킬 수 있다.
- 다른 컴파일러 유형과는 달리, 프로그램이 시작되고 코드를 컴파일한다.
- 기계어로 변환된 코드를 캐시에 저장해서 재사용시 컴파일을 다시 하지 않아도 되기 때문에 동적 컴파일을 하는 다른 언어보다 훨씬 좋은 성능을 낸다.