Search code examples
springstack-overflowmybatis

Tomcat start throw java.lang.StackOverflowError when use spring mybatis


Tomcat start throw java.lang.StackOverflowError when use spring mybatis. Besides, this error occur randomly, it's very weird.

ERROR org.mybatis.spring.mapper.MapperFactoryBean.checkDaoConfig(MapperFactoryBean.java:97) - Error while adding the mapper 'interface com.myWeb.dao.MyClassMapper' to configuration.
java.lang.StackOverflowError
    at java.lang.String.getChars(String.java:783)
    at java.lang.String.concat(String.java:1976)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:357)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:412)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
    at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1603)
    at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1533)
    at org.apache.ibatis.scripting.xmltags.XMLScriptBuilder$ForEachHandler.handleNode(XMLScriptBuilder.java:160)
    at org.apache.ibatis.scripting.xmltags.XMLScriptBuilder.parseDynamicTags(XMLScriptBuilder.java:83)
    at org.apache.ibatis.scripting.xmltags.XMLScriptBuilder.access$800(XMLScriptBuilder.java:35)
    at org.apache.ibatis.scripting.xmltags.XMLScriptBuilder$IfHandler.handleNode(XMLScriptBuilder.java:167)
    at org.apache.ibatis.scripting.xmltags.XMLScriptBuilder$ChooseHandler.handleWhenOtherwiseNodes(XMLScriptBuilder.java:199)
    at org.apache.ibatis.scripting.xmltags.XMLScriptBuilder$ChooseHandler.handleNode(XMLScriptBuilder.java:187)
    at org.apache.ibatis.scripting.xmltags.XMLScriptBuilder.parseDynamicTags(XMLScriptBuilder.java:83)
    at org.apache.ibatis.scripting.xmltags.XMLScriptBuilder.access$800(XMLScriptBuilder.java:35)
    at org.apache.ibatis.scripting.xmltags.XMLScriptBuilder$ForEachHandler.handleNode(XMLScriptBuilder.java:152)
    at org.apache.ibatis.scripting.xmltags.XMLScriptBuilder.parseDynamicTags(XMLScriptBuilder.java:83)
    at org.apache.ibatis.scripting.xmltags.XMLScriptBuilder.access$800(XMLScriptBuilder.java:35)
    at org.apache.ibatis.scripting.xmltags.XMLScriptBuilder$TrimHandler.handleNode(XMLScriptBuilder.java:121)
    at org.apache.ibatis.scripting.xmltags.XMLScriptBuilder.parseDynamicTags(XMLScriptBuilder.java:83)

Solution

  • OMG, after a few days researching, i finally found the problem.it's because Mybatis initiate multilayer recursion when spring creating mapper instance and cause the stack overflow. i trace to the SqlSessionDaoSupport(MapperFactoryBean inherit it) in org.mybatis.spring.support and find this:

    @Autowired(required = false)
    public final void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory)   {
       if (!this.externalSqlSession) {
       this.sqlSession = new SqlSessionTemplate(sqlSessionFactory);
       }
    }
    
    @Autowired(required = false)
    public final void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) {
       this.sqlSession = sqlSessionTemplate;
       this.externalSqlSession = true;
    }
    

    When MapperFactoryBean instance is created, Spring will inject SqlSessionTemplate for it. When injecting SqlSessionTemplate it will gain all the Dao from the container. Dao has been created in the container for the corresponding bean can capture, but if the bean has not been created, then Spring will create the Dao of MapperFactoryBean. when create MapperFactoryBean it will be injection SqlSessionTemplate again. This will be continuing until all of the Dao have been created.So it cause the final stack overflow error casually if you are unlucky.

    In short:it's because my mybatis-spring version is too low(i use the version 1.1.1). And this kind of autowired was removed from setSqlSessionTemplate and setSqlSessionFactory in version 1.2.0.

    So: by changing mybatis-spring version to higher than 1.2.0, this problem was solved.