garbage collector
는 ThreadLocal
변수를 사용하고 있는 스레드가 더 이상 없을 때, 정리 대상으로 판단합니다.
즉 스레드 풀을 사용하는 애플리케이션 서버의 경우 ThreadLocal
을 점유하던 스레드가 재사용될 때 메모리 누수가 발생할 수 있습니다.
이러한 문제를 방지하려면 항상 remove()
메서드를 사용하여 ThreadLocal
변수의 현재 스레드 값을 제거하는 것이 좋습니다.
또한 set(null)
을 호출해서 값을 제거하면, map에 이 포인터에 대한 참조가 유지되어, 메모리 누수가 발생할 수 있습니다.
여러모로 이 문제를 방지하려면 remove()
를 사용하는 것이 더 안전합니다.
규칙을 어긴 코드
public class ThreadLocalUserSession implements UserSession {
private static final ThreadLocal<UserSession> DELEGATE = new ThreadLocal<>();
public UserSession get() {
UserSession session = DELEGATE.get();
if (session != null) {
return session;
}
throw new UnauthorizedException("User is not authenticated");
}
public void set(UserSession session) {
DELEGATE.set(session);
}
public void incorrectCleanup() {
DELEGATE.set(null); // 규칙을 어긴 코드
}
// 이외 DELEGATE.remove()를 호출하지 않은 다른 메소드들
}
규칙을 준수한 해결책
public class ThreadLocalUserSession implements UserSession {
private static final ThreadLocal<UserSession> DELEGATE = new ThreadLocal<>();
public UserSession get() {
UserSession session = DELEGATE.get();
if (session != null) {
return session;
}
throw new UnauthorizedException("User is not authenticated");
}
public void set(UserSession session) {
DELEGATE.set(session);
}
public void unload() {
DELEGATE.remove(); // 규칙을 준수한 해결책
}
// ...
}
같이보면 좋은 자료
- 자바에서 메모리 누수 이해하기 (^역: 이 글이 읽어볼만 합니다.)
If you like SONARKUBE, don’t forget to give me a star.