Analysis of MyBatis OGNL Concurrency Bug and Workarounds
This article investigates a concurrency bug in MyBatis caused by OGNL expression evaluation using reflection, explains the root cause through stack trace and source code analysis, and proposes solutions such as upgrading MyBatis or avoiding private inner‑class methods like Arrays.asList.
To save time, here is the conclusion: there is indeed a problem (see the issue link: https://github.com/mybatis/mybatis-3/pull/384). Below is the source‑code analysis and handling process for those interested.
Bug fixes are mandatory; without fixing them, daily work can be severely disrupted.
Log
After deploying to the server, MyBatis threw an exception on a frequently used interface, threatening performance metrics.
2023-08-08 09:52:05,386|aaaaaaaaa|XXXXXXXXXXXXXX|unknown exception occurred
org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.builder.BuilderException: Error evaluating expression 'projects != null and projects.size() > 0 '. Cause: org.apache.ibatis.ognl.MethodFailedException: Method "size" failed for object [aaa,bbb,ccc] [java.lang.IllegalAccessException: Class org.apache.ibatis.ognl.OgnlRuntime can not access a member of class java.util.Arrays$ArrayList with modifiers "public"]
at org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible(MyBatisExceptionTranslator.java:75) ~[mybatis-spring-1.2.2.jar:1.2.2]
... (stack trace truncated for brevity) ...
Caused by: org.apache.ibatis.builder.BuilderException: Error evaluating expression 'projects != null and projects.size() > 0 '. Cause: org.apache.ibatis.ognl.MethodFailedException: Method "size" failed for object [aaa,bbb,ccc]
at org.apache.ibatis.scripting.xmltags.OgnlCache.getValue(OgnlCache.java:45) ~[mybatis-3.2.8.jar:3.2.8]
... (more frames omitted) ...The error occurs intermittently; most calls work fine, but occasional failures require deeper investigation.
Source Code Analysis
Investigation shows that OGNL expressions obtain methods via reflection and cache them in a static variable, which can cause concurrency issues when multiple threads access the cache.
Below is the caching logic (see the method org.apache.ibatis.ognl.OgnlRuntime#getMethods(java.lang.Class, boolean) for details).
The bug manifests when one thread sets a flag to true while another thread resets it to false before the method is invoked, leading to a failure.
The MyBatis issue tracker confirms this problem: https://github.com/mybatis/mybatis-3/pull/384.
The suggested fix is to upgrade MyBatis, but upgrading may not be feasible in a stable production codebase.
As a workaround, avoid using Arrays.asList (which returns a private inner class) in OGNL expressions. Instead, use Lists.newArrayList or other public‑method alternatives.
Summary
Problem: Non‑public methods or classes used in OGNL expressions can cause concurrency issues.
Solution 1: Upgrade MyBatis to a version where the bug is fixed.
Solution 2: Replace Arrays.asList with Lists.newArrayList or other public‑method collections to avoid the private inner‑class pitfall.
Selected Java Interview Questions
A professional Java tech channel sharing common knowledge to help developers fill gaps. Follow us!
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.