자바 자료구조 강의 수강 중 Linked List를 직접 구현하는 과정에서 궁금증이 생겼다.
특정 노드를 삭제하기 위해 그 노드를 어떤 노드에서도 참조하지 않게만 하면 될 것으로 생각했지만, 해설 코드는 이와 더불어 그 노드가 참조하고 있는 부분까지도 null로 바꾸었다.
GC의 특성상 어떤 객체를 아무 데서도 참조하고 있지 않으면 메모리 상에서 삭제된다고 알고 있었기 때문에, 굳이 그 객체가 참조하고 있는 부분까지 신경을 써줘야 하나?라는 생각이 들었던 것이다.
소스 코드
private class Node {
T data;
Node next;
Node(T data) {
this.data = data;
}
Node(T data, Node next) {
this.data = data;
this.next = next;
}
}
Node클래스
@Override
public boolean delete(T t) {
Node prev = this.head;
Node current = prev.next;
while (current != null) {
if (current.data.equals(t)) {
prev.next = current.next;
current.next = null;
this.size--;
return true;
}
prev = prev.next;
current = current.next;
}
return false;
}
해설 코드
@Override
public boolean delete(T t) {
Node previousNode = head;
Node currentNode = previousNode.next;
while (currentNode.next != null) {
if (currentNode.data.equals(t)) {
previousNode.next = currentNode.next;
size--;
return true;
}
previousNode = previousNode.next;
currentNode = currentNode.next;
}
return false;
}
내 코드

이해를 돕기 위해 소스 코드와, delete메서드 호출 시 LinkedList의 변화를 그림으로 나타내었다.
어쨌든 이 부분에 대해 멘토님께 질문을 드렸고 다음과 같은 답변을 받을 수 있었다.
우선 어떤 객체를 삭제하기 위해 그 객체를 참조하고 있는 부분만 제거해도 GC의 대상이 되어 제거가 되기는 한다.
다만, GC의 동작 방식을 보면, GC는 루트 집합(연결의 시작)에서 시작하여 GC의 대상을 결정하기 위해 개체 간의 참조를 추적한다. 이때 도달 가능한 개체가 아닌 경우 우선순위에 의해 GC처리를 한다.
위 그림에서 내 코드로 구현한 것을 보면 prev의 next가 current.next를 참조하도록 변경했기 때문에, 리스트에서 제거된 current 노드의 참조 경로가 끊겼다고 생각할 수 있으나, current의 next가 여전히 다음 개체를 가리키고 있기 때문에 GC는 reachable한 개체라고 인지하여 수집 우선순위에서 배제한다. 그리고 이후에 실제로 참조되고 있지 않음을 파악한 뒤에 GC처리를 하게 된다.
즉, 내 생각대로 GC처리가 되기는 하나, 시간이 얼마나 걸릴지 모르니 명시적으로 NULL처리를 해서 도달 가능하지 않는 개체로 상태를 변경하는 것이 더 빠른 GC의 수집 대상이 되는 방법이라는 것이다.
참고 - https://velog.io/@maketheworldwise/가비지-컬렉터는-뭘까
'Language > Java' 카테고리의 다른 글
| 메서드 내에서 포장객체의 값을 변경한다면? (0) | 2023.04.25 |
|---|---|
| Java Raw Type의 정의와 사용 시 문제점 (0) | 2023.04.03 |
| 자바의 배열 크기를 바꿀 수 있을까? (0) | 2023.03.26 |
| Java 메서드 인자 전달 메커니즘 (0) | 2023.03.07 |
| Java의 Stack자료구조 (0) | 2023.01.27 |