😀 Jerry/면접 질문

[1분 면접] JVM에서 GC 대상 객체를 판단하는 기준 (+ JVM 구조)

Jerry_K 2025. 4. 14. 12:20

📌 면접 답변

  • GC(Garbage Collection)은 자바의 메모리 관리 방법의 하나
  • JVM의 힙 영역에서 동적으로 할당했던 메모리 중 필요없어진 객체를 주기적으로 제거
  • GC는 특정 객체가 사용 중인지 아닌지를 판단하기 위해 (Reachability) 개념 사용
  • 특정 객체에 대한 참조가 존재하면 도달 할 수 있으며, 참조가 존재하지 않는 경우 도달 할 수 없는 상태로 간주
  • 이때 도달할 수 없다는 결론을 내린다면 해당 객체는 GC의 대상이 된다.

 

Reachability 판단 기준

힙 영역에 있는 객체에 대한 참조는 4가지 케이스가 존재한다.

 

1. 힙 내의 다른 객체에 의한 참조

class Engine {
    String type = "V6";
}

class Car {
    Engine engine; // 힙 내의 다른 객체(Engine)를 참조
    public Car() {
        engine = new Engine(); // Car 객체가 Engine 객체를 참조
    }
}

 

 

2. Java 스택 (지역 변수, 파라미터)에 의한 참조

public class Example {
    public static void main(String[] args) {
        Car car = new Car(); // car는 스택에 존재, Car 객체는 힙에 존재
    }
}
  • car 변수는 스택 변수
  • Car 객체는 힙 

 

3. 네이티브 스택 (JNI에 의해 참조되는 객체) 

  • JNI (Java Native Interface)
    • 여기서 Native(원시)는 C/C++ 같은 native(원시) 언어로 작성된 코드를 의미
  • accessJavaObjectNative() 메서드를 C/C++ 로 구현된 네이티브 코드라 가정  
public class NativeExample {
    static {
        System.loadLibrary("native-lib");
    }

    public native void accessJavaObjectFromNative(Car car);
}
  • C/C++ 등의 네이티브 코드가 Java 객체를 참조하는 경우
  • accessJavaObjectNative() 메서드가 Car 객체에 접급

 

JNI는 꼭 필요한 성능 / 하드웨어 / 레거시의 이유로 쓰일 수는 있다. 

가급적 순수 Java로 해결하고, JNI는 마지막 수단으로 쓴다는 말이 있다. 

 

 

 

4. 메서드 영역의 정적 변수에 의한 참조

public class Garage {
    public static Car sharedCar = new Car(); // 메서드 영역의 static 변수
}
  • sharedCar는 메서드 영영에 존재하고, 힙 객체 참조 가능

 

위에 것들이 힙 영역에 있는 객체에 대한 참조 4가지 케이스이다. 

 

 

https://d2.naver.com/helloworld/329631

 

Reachability의 판단은 아래와 같이 한다.

  • 참조 4가지 케이스 중 힙 내의 다른 객체에 의한 참조를 제외한 나머지를 Root Set(시작점)이라고 한다.
  • RootSet으로부터 시작한 참조 사슬에 속한 객체들을 도달할 수 있는 객체라고 한다.
  • 이 참조 사슬과 무관한 객체들을 도달하기 어렵다고 하고, 이것은 GC의 대상이 된다.
  • 위의 그림을 보면 이해하기 쉽다.

 추가 보충

"JVM의 힙 영역에서 동적으로 할당했던 메모리 중 필요없어진 객체를 주기적으로 제거"

 

Q . JVM의 힙 영역은 우리가 흔히 아는 가상 메모리의 힙 영역과 다른건가 ? 

  • 일반적으로 Java 메모리 구조를 이해할 때는 '가상 메모리'가 아니라 JVM 관점에서 보는게 맞다.
    • Java는 운영체제와 직접 메모리 거래를 하지 않음
    • Java 프로그램은 JVM 위에서 돌아가고, JVM이 대신 OS와 메모리 주고 받음
    • Java 개발에서는 JVM이 만든 메모리 영역만 신경 쓰면된다.
  • Java 메모리 구조
    • 메서드 영역 (클래스, static, 메서드 정보, 바이트코드, 상수 풀 등)
    • 힙 영역 (new로 만든 객체)
    • 스택 영역 (각 스레드별로 할당, 지역변수, 매개변수)
    • PC 레지스터 (현재 실행중인 명령어 주소 저장)
    • 네이티브 메서드 스택 (JNI 등)

 

+ 추가 보충)

Q. Java의 컴파일 과정

 

JVM 덕분에 Java의 소스 코드는 OS로부터 독립적이게 된다. 

Java의 컴파일 순서에 대해 알아보자.

 

  1. 개발자가 .java 소스코드를 작성한다.
  2. 자바 컴파일러에 의해 .class 파일로 변환된다. (아직 컴퓨터는 읽을 수 없고, JVM이 해석 가능)
  3. 컴파일된 코드는 JVM의 Class Loader로 전달된다.
  4. Class Loader는 동적 로딩을 통해 필요한 클래스들을 로딩 및 링크하여 런타임 데이터 영역 (JVM) 메모리에 로드
  5. 실행 엔진
    (Interpreter는 바이트 코드 명령어 하나씩 읽어서 해석, JIT 컴파일러는 바이트 코드 전체를 컴파일하여 바이너리 코드로 변경)

 

 

+ 추가 보충)

Q. C언어 컴파일 과정 

 C언어 컴파일 과정은 크게 4가지로 이뤄져있다. 

전처리 → 컴파일 → 어셈블 → 링크

 

  1. 전처리 과정에서는 프로그램에 필요한 헤더 파일을 소스코드로 복사 및 주석 삭제 등의 작업
  2. 컴파일러 과정에서는 고수준 언어를 저수준 언어로 나타내는 역할 (어셈블리어로 변환)
  3. 어셈블 과정에서는 어셈블리어를 기계어로 바꾸는 과정을 거치며 Object File로 변환 (사람이 읽을 수 없음) 
  4. 링커 과정에서는 오브젝트 파일들과 프로그램 실행에 필요한 라이브러리 파일 결합해서 하나의 실행 파일로 만듬

 

 

Java 컴파일과 C 컴파일의 가장 큰 차이점은 아래와 같다.

  • Java의 바이트 코드는 OS/CPU에 종속되지 않고, JVM이 있으면 어디서든 실행 가능하다
  • C는 OS/CPU 마다 다시 컴파일 과정을 거쳐야하지만, JVM 같은 중간 단계를 거치지 않아 성능이 높다.

📌 내 답변

JVM의 GC는 수명이 다한 객체의 힙 영역 메모리를 회수하고 지우는 역할을 한다.

대상 객체는 오랫동안 쓰이지 않는 것들이 대상이 될 것이다.

 

Self Feedback

  • Reachability에 대한 개념에 대해 알지 못했다. 
  • 힙 영역에 있는 객체에 대한 참조는 4가지 케이스에 대해서도 잘 몰랐다.
  • JVM에 대한 개념이 부족해서 추가적으로 정리하였다.
  • 추가로 JVM 컴파일 과정을 공부하면서 C 언어 컴파일 과정도 도움이 될 것 같아 짧게 정리해보았다.

[출처 및 참고 자료]

https://www.maeil-mail.kr/question/155

 

매일메일 - 기술 면접 질문 구독 서비스

기술 면접 질문을 매일매일 메일로 보내드릴게요!

www.maeil-mail.kr

 

 

https://d2.naver.com/helloworld/329631