rspec/rules/S5164/java/rule.adoc

99 lines
2.4 KiB
Plaintext
Raw Permalink Normal View History

== Why is this an issue?
2021-04-28 16:49:39 +02:00
``++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 threads 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
2021-04-28 16:49:39 +02:00
2022-02-04 17:28:24 +01:00
[source,java]
2021-04-28 16:49:39 +02:00
----
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
2021-04-28 16:49:39 +02:00
2022-02-04 17:28:24 +01:00
[source,java]
2021-04-28 16:49:39 +02:00
----
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
2021-04-28 16:49:39 +02:00
Rule will not detect non-private ``++ThreadLocal++`` variables, because ``++remove()++`` can be called from another class.
== Resources
2021-04-28 16:49:39 +02:00
* https://www.baeldung.com/java-memory-leaks[Understanding Memory Leaks in Java]
ifdef::env-github,rspecator-view[]
'''
== Implementation Specification
(visible only on this page)
=== Message
Call the "remove()" on "XXX".
'''
== Comments And Links
(visible only on this page)
=== on 25 Jul 2019, 18:38:21 Tibor Blenessy wrote:
For reference, issue in spring-cloud \https://github.com/spring-cloud/spring-cloud-sleuth/issues/27
endif::env-github,rspecator-view[]