TIL

[TIL-58/240615] 기술면접(자바)

prao 2024. 6. 15. 22:23
반응형

기술면접 질문(자바)

Java의 특징을 설명하라.
Java는 대표적인 객체지향 프로그래밍 언어로써 기본 자료형을 제외한 모든 요소들이 객체로 표현되고, 객체 지향 개념의 특징인 캡슐화, 상속, 다형성이 잘 적용된 언어입니다.
장점으로썬 JVM 위에서 동작하기 때문에 운영체제에 독립적이고,
가비지 컬렉터를 통한 자동적인 메모리 관리가 가능하다가 있습니다.
단점으로썬 JVM 위에서 동작하기 때문에 실행 속도가 상대적으로 느리고,
다중 상속이나 타입에 엄격하여 제약이 많다가 있습니다.

 

JVM의 역할에 대해 설명하라.
JVM은 스택 기반으로 동작하며, Java Byte Code를 OS에 맞게 해석해주는 역할을 하고 가비지 컬렉션을 통해 자동적인 메모리 관리를 해준다.

 

자바 애플리케이션의 구동 원리를 설명하라.

자바 애플리케이션의 구동원리

자바 애플리케이션의 구동 원리는 크게 5단계로 나눌 수 있습니다.

1. 소스코드 작성

자바 프로그램 소스코드를 .java의 확장자를 가진 파일에 작성합니다.

2. 컴파일

자바 컴파일러는 javac을 사용하여 .java 파일을 컴파일합니다.

이 과정에서 자바 소스 코드가 바이트코드로 변환되며, 이는 .class 확장자를 가진 파일에 저장됩니다.

javac MyProgram.java

위 명령어를 실행하면 MyProgram.class 파일이 생성됩니다.

3. 클래스 로딩

자바 프로그램을 실행할 때, JVM은 필요한 클래스 파일들을 메모리에 로드합니다.

클래스 로더는 이러한 클래스 파일들을 로드하고, 각 클래스의 바이트코드를 읽어 메모리에 적재합니다.

4. 바이트코드 검증

로딩된 바이트코드는 자바 검증기에 의해 검증됩니다.

이 과정에서는 바이트코드가 유효한지, 그리고 자바 언어의 규칙을 준수하는지를 검사합니다.

5. 실행 엔진(Execution Engine)

검증된 바이트코드는 JVM의 실행 엔진에 의해 실행됩니다.

6. 실행

JVM은 바이트코드를 실행하고, 프로그램의 결과를 생성합니다.

실행 중에 JVM은 메모리 관련(가비지 컬렉션), 스레드 관리, 예외 처리 등 다양한 런타임 서비스를 제공합니다.

 

JVM의 동작 방식에 대해 설명하라

JVM의 역할은 자바 애플리케이션을 클래스 로더를 통해 읽어 자바 API와 함께 실행하는 것입니다.

JVM 동작 도식도

  1. 자바 프로그램을 실행하면 JVM은 OS로부터 메모리를 할당 받음
  2. 자바 컴파일러(javac)가 자바 소스코드(.java)를 자바 바이트 코드(.class)로 컴파일함
  3. Class Loader는 동적 로딩을 통해 필요한 클래스들을 로딩 및 링크하여 Runtime Data Area(실질적인 메모리를 할당받아 관리하는 영역)에 올림
  4. Runtime Data Area에 로딩된 바이트 코드는 Execution Engine을 통해 해석됨
  5. 이 과정에서 Execution Engine에 의해 가비지 컬렉터의 작동과 Thread 동기화가 이뤄짐

 

JVM의 구조에 대해 설명하라(~JIT Compiler & Interpreter까지, Garbage Collector는 따로 설명)

아래 그림은 Class Loader - Execution Engine - Runtime Data Area 부분을 상세화한 도식

도식도

JVM의 구성은 다음과 같다.

  1. 클래스 로더(Class Loader)
  2. 실행 엔진(Execution Engine)
    1. 인터프리터(Interpreter)
    2. JIT 컴파일러(Just-In-Time)
    3. 가비지 콜렉터(Garbage Collector)
  3. 런타임 데이터 영역(Runtime Data Area)
    1. 메소드 영역
    2. 힙 영역
    3. PC Register
    4. 스택 영역
    5. 네이티브 메소드
  4. JNI - 네이티브 메소드 인터페이스(Native Method Interface)
  5. 네이티브 메소드 라이브러리(Native Method Library)

클래스 로더(Class Loader)

클래스 로더

클래스 로더는 JVM 내로 클래스 파일(*.class)을 동적으로 로드하고, 링크를 통해 배치하는 작업을 수행하는 모듈

즉, 로드된 바이트 코드(.class)들을 엮어서 JVM의 메모리 영역인 Runtime Data Areas에 배치함

클래스를 메모리에 올리는 로딩 기능은 한번에 메모리에 올리지 않고, 어플리케이션에서 필요한 경우 동적으로 메모리에 적재함

 

클래스를 로드하는 과정은 Loading → Linking → Initialization 3단계로 구성됨

클래스 로드 과정

  1. Loading(로드): 클래스 파일을 가져와서 JVM의 메모리에 로드
  2. Linking(링크): 클래스 파일을 사용하기 위해 검증하는 과정
    1. Verifying(검증): 읽어들인 클래스가 JVM 명세에 명시된대로 구성되어 있는지 검사
    2. Preparing(준비): 클래스가 필요로 하는 메모리에  할당
    3. Resolving(분석): 클래스의 상수 풀 내 모든 심볼릭 레퍼런스를 다이렉트 레퍼런스로 변경
  3. Initialization(초기화): 클래스 변수들을 적절한 값으로 초기화(static 필드들을 설정된 값으로 초기화)

실행 엔진(Execution Engine)

실행 엔진은 클래스 로더를 통해 런타임 데이터 영역에 배치된 바이트 코드를 명령어 단위로 읽어서 실행

자바 바이트 코드(.class)는 기계가 바로 수행할 수 있는 언어보다 가상머신이 이해할 수 있는 중간 레벨로 컴파일된 코드

실행 엔진은 이와 같은 바이트 코드를 실제로 JVM 내부에서 기계가 실행할 수 있는 형태로 변경해줌

실행 엔진은 인터프리터와 JIT 컴파일러 두 가지 방식을 혼합하여 바이트 코드를 실행

실행 엔진 동작

 

인터프리터(Interpreter)

바이트 코드 명령어를 하나씩 읽어서 해석하고 바로 실행

JVM 안에서 바이트 코드는 기본적으로 인터프리터 방식으로 동작

다만 같은 메소드라도 여러 번 호출이 된다면 매번 해석하고 수행해야 하므로 전체적인 속도는 느림

 

JIT 컴파일러(Just-In-Time Compiler)

Interpreter의 단점을 보완하기 위해 도입된 방식으로 반복되는 코드를 발견하여 바이트 코드 전체를 컴파일하여 Native Code로 변경하고 이후에는 해당 메소드를 더 이상 인터프리팅하지 않고 캐싱해 두었다가 네이티브 코드로 직접 실행하는 방식

하나씩 인터프리팅하여 실행하는 것이 아닌 컴파일된 네이티브 코드를 실행하는 것이기 때문에 전체적인 실행 속도는 인터프리팅 방식보다 빠름

하지만 바이트 코드를 Native Code로 변환하는 데 비용 발생 → JVM은 모든 코드를 JIT 컴파일러 방식으로 실행하지 않고 인터프리팅 방식을 사용하다 일정 기준이 넘어가면 JIT 컴파일 형식으로 명령어를 실행하는 식으로 진행

(네이티브 코드: Java에서 부모가 되는 C언어나 C++, 어셈블리어로 구성된 코드를 의미)

 

반응형