Skip to content

Fix ErrorContext ThreadLocal memory leak in lazy loading#3636

Merged
hazendaz merged 1 commit intomybatis:masterfrom
jisub-dev:fix/errorcontext-threadlocal-leak
Feb 15, 2026
Merged

Fix ErrorContext ThreadLocal memory leak in lazy loading#3636
hazendaz merged 1 commit intomybatis:masterfrom
jisub-dev:fix/errorcontext-threadlocal-leak

Conversation

@jisub-dev
Copy link
Copy Markdown
Contributor

Summary

Fixes a ThreadLocal memory leak in ErrorContext when lazy loading is triggered through
proxy method interception.

Problem

When lazy loading is invoked via proxy objects (Javassist/CGLIB proxies or
deserialization proxies), the ErrorContext populated during query execution was not
being cleaned up from ThreadLocal. This caused memory leaks in thread pool environments
like Tomcat, as reported in #1967.

The leak occurred because:

  1. Lazy loading triggers BaseExecutor.query() which populates
    ErrorContext.instance()
  2. Proxy interceptor methods had no ErrorContext.reset() in their finally blocks
  3. ThreadLocal references remained in threads, preventing garbage collection

Solution

Added ErrorContext.instance().reset() calls in the finally blocks of:

  • JavassistProxyFactory.EnhancedResultObjectProxyImpl.invoke()
  • CglibProxyFactory.EnhancedResultObjectProxyImpl.intercept()
  • AbstractEnhancedDeserializationProxy.invoke()

Testing

  • Existing tests pass (ErrorContextTest)
  • No regression in lazy loading functionality
  • Memory leak is prevented by cleaning up ThreadLocal after lazy loading

Closes #1967

When lazy loading is triggered through proxy method interception,
ErrorContext was not being cleaned up, causing ThreadLocal memory leaks.

Add ErrorContext.reset() in proxy finally blocks to prevent the leak.

Fixes mybatisgh-1967

Signed-off-by: jisub-dev <[email protected]>
@coveralls
Copy link
Copy Markdown

Coverage Status

coverage: 87.423% (+0.003%) from 87.42%
when pulling b13415e on jisub-dev:fix/errorcontext-threadlocal-leak
into 71bdeb3 on mybatis:master.

@hazendaz hazendaz merged commit 199455f into mybatis:master Feb 15, 2026
1 check passed
@hazendaz
Copy link
Copy Markdown
Member

@jisub-dev Thank you! I used AI as not super familiar with this area of code. Gist I got from that is that the normal locations that is reset were properly in try finally blocks but with proxies, those are long done due to the lazy loading so there is no finally to cleanup. Where you added it then is correct in all three spots as the two proxies both interact and override parts of that base class. Thanks for picking up such an old issue and taking care of it.

@hazendaz hazendaz self-assigned this Feb 15, 2026
@hazendaz hazendaz added this to the 3.6.x milestone Feb 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Does not remove an ErrorContext from ThreadLocal when use the lazy loading

3 participants