90 lines
2.2 KiB
Plaintext
90 lines
2.2 KiB
Plaintext
``++ThreadLocal++`` variables are supposed to be garbage collected once the holding thread is no longer alive. Memory leaks can occur when holding threads are re-used which is the case on application servers using pool of threads.
|
||
|
||
To avoid such problems, it is recommended to always clean up ``++ThreadLocal++`` variables using the ``++remove()++`` method to remove the current thread’s value for the ``++ThreadLocal++`` variable.
|
||
|
||
|
||
In addition, calling ``++set(null)++`` to remove the value might keep the reference to ``++this++`` pointer in the map, which can cause memory leak in some scenarios. Using ``++remove++`` is safer to avoid this issue.
|
||
|
||
|
||
== Noncompliant Code Example
|
||
|
||
----
|
||
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); // Noncompliant
|
||
}
|
||
|
||
// some other methods without a call to DELEGATE.remove()
|
||
}
|
||
----
|
||
|
||
|
||
== Compliant Solution
|
||
|
||
----
|
||
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(); // Compliant
|
||
}
|
||
|
||
// ...
|
||
}
|
||
----
|
||
|
||
|
||
== Exceptions
|
||
|
||
Rule will not detect non-private ``++ThreadLocal++`` variables, because ``++remove()++`` can be called from another class.
|
||
|
||
|
||
== See
|
||
|
||
* https://www.baeldung.com/java-memory-leaks[Understanding Memory Leaks in Java]
|
||
|
||
|
||
|
||
ifdef::env-github,rspecator-view[]
|
||
|
||
'''
|
||
== Implementation Specification
|
||
(visible only on this page)
|
||
|
||
include::message.adoc[]
|
||
|
||
'''
|
||
== Comments And Links
|
||
(visible only on this page)
|
||
|
||
include::comments-and-links.adoc[]
|
||
endif::env-github,rspecator-view[]
|