Q. JVM의 스택과 힙메모리 영역에 대해 아는 만큼 설명해주실 수 있을까요?
A.
Java Virtual Machine(JVM)의 스택과 힙 메모리 영역에 대해 설명하겠습니다.
먼저, JVM 내부에는 'Runtime Data Areas'라는 바이트코드를 실행시키기 위해 필요한 메모리 공간이 존재합니다. Runtime Data Areas에 Heap과 Stack이 있고 Method area, PC registers, Native method stacks 등의 다른 메모리 공간도 존재합니다.
힙(Heap)은 프로그램이 실행되는 동안 생성되는 객체를 저장하는 메모리 영역으로, 모든 스레드가 공유하는 공간입니다. 객체는 힙에 생성되고, 객체에 대한 참조는 스택에 저장됩니다. 힙에 저장된 객체는 JVM의 가비지 컬렉터에 의해 관리되며, 더 이상 참조되지 않는 객체는 가비지 컬렉터에 의해 제거됩니다. 이렇게 힙은 동적으로 메모리를 할당받아 사용하므로, 실행 중에 메모리 요구 사항이 변경되는 경우에도 유연하게 대응할 수 있습니다.
스택(Stack)은 각각의 스레드마다 존재하는 메모리 공간입니다. 스택(Stack)은 메서드가 호출될 때마다 생성되는 스택 프레임(Stack Frame)을 저장하는 공간입니다. 스택 프레임 내에는 'Local variables array', 'Operand stack', 그리고 'Frame Data'가 포함되어 있는데, 이 세 가지 영역은 메서드의 로컬 변수, 매개변수, 연산 중 발생하는 임시 데이터 등을 저장하여 메서드 실행 중 필요한 데이터를 저장하고 관리하는 역할을 수행합니다.스택은 후입선출(LIFO, Last In First Out)의 원칙에 따라 동작하며, 메서드의 호출이 완료되면 해당 메서드에 대한 스택 프레임은 스택에서 제거(pop)됩니다. 스레드가 완전히 종료되면 해당 스레드의 스택도 함께 소멸됩니다.
이렇게 JVM의 스택과 힙은 각자의 역할을 가지고 있으며, 이 두 영역의 특성을 이해하는 것은 자바 프로그래밍에서 효율적인 메모리 관리에 중요합니다.
Q. 클래스와 인스턴스의 차이에 대해 설명해주실 수 있을까요?
A.
클래스와 인스턴스 차이
클래스란 객체를 생성하기 위한 틀이나 설계도와 같은 개념입니다. 클래스는 특정 객체의 속성(attribute)과 행동(method)을 정의하고 있습니다. 예를 들어, '자동차'라는 클래스가 있다면, 이 클래스는 속성으로 '색깔', '브랜드', '모델' 등을 가지고, 행동으로는 '달리기', '멈추기' 등을 가질 수 있습니다.
반면, 인스턴스는 클래스를 기반으로 실제로 생성된 객체를 의미합니다. 클래스는 설계도라면, 인스턴스는 그 설계도를 바탕으로 실제로 만들어진 '제품'이라고 볼 수 있습니다. 위의 예를 이어가보면, '자동차'라는 클래스를 바탕으로 만들어진 '흰색의 테슬라 모델 S'는 인스턴스입니다.
즉, 클래스는 '개념'이나 '설계도'에 가깝고, 인스턴스는 그 '개념'을 바탕으로 '실체화'된 것이라는 차이가 있습니다. 이렇게 클래스로부터 인스턴스를 생성하는 것을 '인스턴스화'라고 합니다. 그래서 프로그래밍에서는 특정 클래스의 인스턴스를 만들어서 그 인스턴스가 가진 속성이나 메소드를 사용하는 방식이 일반적입니다.
Q. Garbage Collector의 역할, 원리, 알고리즘에 대해 아는 만큼 설명해주실 수 있을까요?
A.
1. 역할
- 프로그램이 동적으로 할당했던 메모리 영역(Heap 영역) 중 필요없게 된 영역(어떠한 변수도 가리키지 않는 객체)을 알아서 해제시켜줍니다.
- C/C++의 경우는 코드 레벨에서 수동으로 메모리를 할당받고 해제해야 한다. 이 때문에 동적 메모리를 해제하지 않아 Memory Leak이 발생하거나, 이중으로 메모리를 해제하는 휴먼에러가 발생할 수 있다.
하지만 Java의 경우 동적 메모리 영역 해제를 GC가 알아서 해줍니다. 이는 개발자에 실수로 인한 메모리 누수를 방지하고 해제된 메모리를 이중으로 해제하는 실수를 방지할 수 있습니다.
하지만 GC 작업은 어떠한 메모리 영역이 해제의 대상이 될지 검사하고 해제하는 일은 오버헤드를 증가시키고, GC의 메모리 해제 타이밍을 개발자가 정확히 알기 힘들다는 단점이 있습니다. 이 때문에 실시간성이 매우 강조되는 프로그램의 경우 GC에게 메모리 관리를 맡기는 것이 알맞지 않을 수 있습니다.
2. 원리 / 알고리즘
GC가 어떻게 해제할 동적 메모리 영역들을 검사하는지 설명드리겠습니다. 설명드리기 위해 Root Space라는 개념을 설명드리겠습니다. Root Space는 힙 영역 참조를 담은 변수라고 생각하면 됩니다.
RootSpace
- Stack의 로컬 변수
- Method Area의 Static 변수
- Native Method Stack의 JNI 참조
Reference Counting 방식
→ 순환 참조에 의해 Reference Count가 1로 유지되어, 메모리 영역이 해제되지 못하는 문제 발생!
Mark and Sweep 방식
→ Reference Counting의 순환 참조 문제를 해결할 수 있습니다. 루트에서부터 접근 가능한지가 해제의 기준이 됩니다. 루트부터 그래프 순회를 통해 연결된 객체들(reachable)을 찾아내고(Mark) 연결이 끊어진 객체들(unreachable)을 지우는 방식(Sweep)입니다. 이러한 작업이 끝나면 힙 메모리의 분산되어 있던 메모리가 예쁘게 정리됩니다. 이를 메모리 파편화를 막는 Compaction이라고 합니다.
Mark and Sweep의 특징
1. 의도적으로 GC를 실행시켜야 한다.
: 애플리케이션이 GC에게 컴퓨터 리소스들을 넘겨줘야 하기 때문에 애플리케이션의 사용성을 유지하면서 효율적인 GC의 실행하도록 최적화하는 것이 어렵습니다.
2. 애플리케이션 실행과 GC 실행이 병행된다.
※ 참조
'CS' 카테고리의 다른 글
[항해 취업코스] 개발자 취준 기록 5일차 (0) | 2024.03.12 |
---|---|
[항해 취업코스] 개발자 취준 기록 4일차 (1) | 2024.03.08 |
JDBC의 이해 (0) | 2024.03.07 |
[항해 취업코스] 개발자 취준 기록 2일차 (0) | 2024.03.06 |
[항해 취업코스] 개발자 취준 기록 1일차 (0) | 2024.03.06 |