Announcement Announcement Module
Collapse
No announcement yet.
Spring + MyBatis + Tomcat 7 = memory leak Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Spring + MyBatis + Tomcat 7 = memory leak

    Hi All,

    I currently having the following memory leaks

    Code:
    Jan 15, 2013 2:33:34 PM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
    SEVERE: The web application [/ArcaneAeon] appears to have started a thread named [com.google.common.base.internal.Finalizer] but has failed to stop it. This is very likely to create a memory leak.
    Jan 15, 2013 2:33:34 PM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
    SEVERE: The web application [/ArcaneAeon] appears to have started a thread named [Memcached IO over {MemcachedConnection to /221.133.9.157:10000}] but has failed to stop it. This is very likely to create a memory leak.
    Jan 15, 2013 2:33:34 PM org.apache.catalina.loader.WebappClassLoader checkThreadLocalMapForLeaks
    SEVERE: The web application [/ArcaneAeon] created a ThreadLocal with key of type [jsr166y.ThreadLocalRandom$1] (value [jsr166y.ThreadLocalRandom$1@2bc6a19f]) and a value of type [jsr166y.ThreadLocalRandom] (value [jsr166y.ThreadLocalRandom@7d9ce42c]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak.
    Jan 15, 2013 2:33:34 PM org.apache.catalina.loader.WebappClassLoader checkThreadLocalMapForLeaks
    SEVERE: The web application [/ArcaneAeon] created a ThreadLocal with key of type [java.lang.ThreadLocal] (value [java.lang.ThreadLocal@47484521]) and a value of type [org.apache.ibatis.jdbc.SqlBuilder.SQL] (value [org.apache.ibatis.jdbc.SqlBuilder$SQL@59b29e16]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak.
    Jan 15, 2013 2:33:34 PM org.apache.catalina.loader.WebappClassLoader checkThreadLocalMapForLeaks
    SEVERE: The web application [/ArcaneAeon] created a ThreadLocal with key of type [jsr166y.ThreadLocalRandom$1] (value [jsr166y.ThreadLocalRandom$1@2bc6a19f]) and a value of type [jsr166y.ThreadLocalRandom] (value [jsr166y.ThreadLocalRandom@5da8e45b]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak.
    Jan 15, 2013 2:33:34 PM org.apache.catalina.loader.WebappClassLoader checkThreadLocalMapForLeaks
    SEVERE: The web application [/ArcaneAeon] created a ThreadLocal with key of type [java.lang.ThreadLocal] (value [java.lang.ThreadLocal@47484521]) and a value of type [org.apache.ibatis.jdbc.SqlBuilder.SQL] (value [org.apache.ibatis.jdbc.SqlBuilder$SQL@7b284266]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak.
    Jan 15, 2013 2:33:34 PM org.apache.catalina.loader.WebappClassLoader checkThreadLocalMapForLeaks
    SEVERE: The web application [/ArcaneAeon] created a ThreadLocal with key of type [java.lang.ThreadLocal] (value [java.lang.ThreadLocal@47484521]) and a value of type [org.apache.ibatis.jdbc.SqlBuilder.SQL] (value [org.apache.ibatis.jdbc.SqlBuilder$SQL@101f75b5]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak.
    The number of SQLBuilder leaks increase as the number of database accesses increase.

    any help is highly appreciated.
    Last edited by eviljan; Jan 15th, 2013, 10:44 AM.

  • #2
    And why is this a spring issue? Spring doesn't have MyBatis integration that is provided by the MyBatis project itself not Spring so to address these issues you really have to be on that project...

    Comment


    • #3
      Originally posted by Marten Deinum View Post
      And why is this a spring issue? Spring doesn't have MyBatis integration that is provided by the MyBatis project itself not Spring so to address these issues you really have to be on that project...
      I posted here since I have not found any discussion regarding to this kind of leak. It might be my misconfiguration of Spring + Mybatis and therefore asking for your experience.

      Comment


      • #4
        Without configuration that is hard to tell. Also what you see is an indication it doesn't have to be a memory leak (probably is if you hot redeploy your application).

        Comment


        • #5
          Originally posted by Marten Deinum View Post
          Without configuration that is hard to tell. Also what you see is an indication it doesn't have to be a memory leak (probably is if you hot redeploy your application).
          Thank all,

          It's not hot deploy tho. Those happen when I stop the server and it seems that the SQLBuilder + jsr166y.ThreadLocalRandom warnings increase as you have more data accessing to the database.

          here is the configuration file

          root-context.xml
          Code:
          <?xml version="1.0" encoding="UTF-8"?>
          <beans xmlns="http://www.springframework.org/schema/beans"
              xmlns:p="http://www.springframework.org/schema/p"
          	xmlns:context="http://www.springframework.org/schema/context"
              xmlns:security="http://www.springframework.org/schema/security"
          	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
          	xsi:schemaLocation="
          			http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
          			http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
                      http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">
          
          	<!-- Root Context: defines shared resources visible to all other web components -->
          	<context:annotation-config /> 
          	<context:component-scan base-package="com.firefly.lcgame" />
          	
          	<!-- Load Properties Files -->
          	<context:property-placeholder location="classpath:*-${environment}.properties"/>
          
          	<!-- Spring Data Redis -->
          	<bean id="connectionFactory"
          		class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
          		<property name="hostName" value="${redis.host}" />
          		<property name="port" value="${redis.port}" />
          		<property name="password" value="${redis.pass}" />
          		<property name="usePool" value="${redis.pooling}" />
          		<property name="poolConfig" ref="jedisPoolConfig" />
          	</bean>
          	<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
          		<property name="maxActive" value="${redis.maxActive}" />
          		<property name="minIdle" value="${redis.minIdle}" />
          		<property name="testOnBorrow" value="${redis.testOnBorrow}" />
          	</bean>
          
          	<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
          	    <property name="connectionFactory" ref="connectionFactory"/>
          	    <property name="keySerializer">
          	        <bean id="keyStringSerializer" class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
          	    </property>
          	</bean>
          	
          	<!-- BoneCP configuration -->
          	<bean id="dataSource" class="com.jolbox.bonecp.BoneCPDataSource" destroy-method="close">
          		<property name="driverClass" value="${jdbc.driverClassName}" />
          		<property name="jdbcUrl" value="${jdbc.url}" />
          		<property name="username" value="${jdbc.username}"/>
          		<property name="password" value="${jdbc.password}"/>
          		<property name="idleConnectionTestPeriodInMinutes" value="${boneCP.idleConnectionTestPeriodInMinutes}"/>
          		<property name="idleMaxAgeInMinutes" value="${boneCP.idleMaxAgeInMinutes}"/>
          		<property name="maxConnectionsPerPartition" value="${boneCP.maxConnectionsPerPartition}"/>
          		<property name="minConnectionsPerPartition" value="${boneCP.minConnectionsPerPartition}"/>
          		<property name="partitionCount" value="${boneCP.partitionCount}"/>
          		<property name="acquireIncrement" value="${boneCP.acquireIncrement}"/>
          		<property name="statementsCacheSize" value="${boneCP.statementsCacheSize}"/>
          		<property name="releaseHelperThreads" value="${boneCP.releaseHelperThreads}"/>
          		<property name="lazyInit" value="true"/>
          		<property name="maxConnectionAgeInSeconds" value="${boneCP.maxConnectionAgeInSeconds}"/>
          	</bean>
          
          	<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
          		<property name="dataSource" ref="dataSource" />
          		<property name="configLocation" value="classpath:mybatis-config.xml" />
          	</bean>
          
          	<bean id="transactionManager"
          		class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
          		<property name="dataSource" ref="dataSource" />
          	</bean>
          
          	<bean id="mappers" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
          		<property name="basePackage" value="com.firefly.lcgame.dao" />
          		<!-- <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" /> -->
          	</bean>
              
              <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"/>
          
          	<bean
          		class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
          		<property name="messageConverters">
          			<list>
          				<ref bean="jsonConverter" />
          				<!-- <ref bean="marshallingConverter" />
          				<ref bean="atomConverter" /> -->
          			</list>
          		</property>
          	</bean>
          
          	<bean id="jsonConverter"
          		class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
          		<property name="supportedMediaTypes" value="application/json" />
          	</bean>
              
              <bean id="localeResolver" class="org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver"/>
          
              <!-- localization -->
              <bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource"
                p:fallbackToSystemLocale="false" p:useCodeAsDefaultMessage="true" p:defaultEncoding="UTF-8">
                <description>Base message source to handle internationalization</description>
                <property name="basenames">
                  <list>
                    <value>classpath:localization/messages</value>
                  </list>
                </property>
              </bean>
          
              <bean id="annotationMethodHandlerExceptionResolver" class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver">
                <property name="order" value="0"/>
              </bean>
              <bean id="restExceptionResolver" class="com.firefly.lcgame.exceptions.handler.RestExceptionHandler">
                <property name="order" value="100"></property>
                <property name="errorResolver">
                  <bean class="com.firefly.lcgame.exceptions.handler.DefaultRestErrorResolver">
                    <property name="localeResolver" ref="localeResolver"></property>
                    <!-- <property name="defaultMoreInfoUrl" value="mailto:[email protected]"></property> -->
                    <property name="exceptionMappingDefinitions">
                      <map>
                        <!-- 404 -->
                        <entry key="com.firefly.lcgame.exceptions.InvalidAccessExeption" value="404, 1, error.invalid.access,  _exmsg"></entry>
                        <!-- 500 (catch all): -->
                        <entry key="Throwable" value="500, 1, error.internal, _exmsg"></entry>
                      </map>
                    </property>
                  </bean>
                </property>
              </bean>
            
            <!-- Secure Rest Service Configuration -->
              <!-- <security:http create-session="never" entry-point-ref="digestEntryPoint">
                <security:intercept-url pattern="/duty/stages**" access="ROLE_USER, ROLE_ADMIN" />
                <security:http-basic />
                <security:custom-filter ref="digestFilter" after="BASIC_AUTH_FILTER" />
              </security:http> -->
              
              <security:http pattern="/login**"  security="none">
              </security:http>
          
              <security:http pattern="/dummy**">
                <security:intercept-url pattern="/dummy**" access="ROLE_USER, ROLE_ADMIN"/>
                <security:http-basic/>
              </security:http>
          
              <security:http pattern="/**" entry-point-ref="digestEntryPoint" >
                <security:intercept-url pattern="/**" access="ROLE_USER, ROLE_ADMIN"/>
                <security:custom-filter ref="digestFilter" position="BASIC_AUTH_FILTER"/>
              </security:http>
              
              <bean id="digestFilter" class="org.springframework.security.web.authentication.www.DigestAuthenticationFilter">
                 <property name="userDetailsService" ref="userService" />
                 <property name="authenticationEntryPoint" ref="digestEntryPoint" />
              </bean>
           
              <bean id="digestEntryPoint" class="org.springframework.security.web.authentication.www.DigestAuthenticationEntryPoint">
                <property name="realmName" value="Arcane Aeon Digest Secure REST-WS"/>
                <property name="key" value="xxxxxxxxxxxx"/>
                <property name="nonceValiditySeconds" value="10"/>
              </bean>
              
              <security:authentication-manager>
                <security:authentication-provider user-service-ref="userService"/>
              </security:authentication-manager>
              
              <bean id="userService" class="com.firefly.lcgame.services.CustomerUserDetailsService">
              </bean>
              
              <bean id="connectionManager" class="org.apache.http.impl.conn.PoolingClientConnectionManager" destroy-method="shutdown">
                  <property name="defaultMaxPerRoute" value="${http.defaultMaxPerRoute}" />
                  <property name="maxTotal" value="${http.maxTotal}" />
              </bean>
          
              <bean id="httpClient" class="com.firefly.lcgame.util.ThreadedHttpClient">
                  <property name="connectionManager" ref="connectionManager" />
              </bean>
          </beans>

          Comment


          • #6
            Originally posted by Marten Deinum View Post
            Without configuration that is hard to tell. Also what you see is an indication it doesn't have to be a memory leak (probably is if you hot redeploy your application).
            Hi Marten,

            I think it's memory leak because the number of SQLBuilder and jsr166y.ThreadLocalRandom threads increases overtime. The more the database is accessed, the more of those I found when I stop the server

            here is part of the config regarding to Mybatis
            Code:
            <!-- BoneCP configuration -->
            	<bean id="dataSource" class="com.jolbox.bonecp.BoneCPDataSource" destroy-method="close">
            		<property name="driverClass" value="${jdbc.driverClassName}" />
            		<property name="jdbcUrl" value="${jdbc.url}" />
            		<property name="username" value="${jdbc.username}"/>
            		<property name="password" value="${jdbc.password}"/>
            		<property name="idleConnectionTestPeriodInMinutes" value="${boneCP.idleConnectionTestPeriodInMinutes}"/>
            		<property name="idleMaxAgeInMinutes" value="${boneCP.idleMaxAgeInMinutes}"/>
            		<property name="maxConnectionsPerPartition" value="${boneCP.maxConnectionsPerPartition}"/>
            		<property name="minConnectionsPerPartition" value="${boneCP.minConnectionsPerPartition}"/>
            		<property name="partitionCount" value="${boneCP.partitionCount}"/>
            		<property name="acquireIncrement" value="${boneCP.acquireIncrement}"/>
            		<property name="statementsCacheSize" value="${boneCP.statementsCacheSize}"/>
            		<property name="releaseHelperThreads" value="${boneCP.releaseHelperThreads}"/>
            		<property name="lazyInit" value="true"/>
            		<property name="maxConnectionAgeInSeconds" value="${boneCP.maxConnectionAgeInSeconds}"/>
            	</bean>
            
            	<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
            		<property name="dataSource" ref="dataSource" />
            		<property name="configLocation" value="classpath:mybatis-config.xml" />
            	</bean>
            
            	<bean id="transactionManager"
            		class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            		<property name="dataSource" ref="dataSource" />
            	</bean>
            
            	<bean id="mappers" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
            		<property name="basePackage" value="com.firefly.lcgame.dao" />
            		<!-- <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" /> -->
            	</bean>
            mybatis config
            Code:
            <?xml version="1.0" encoding="UTF-8" ?>
            <!DOCTYPE configuration
              PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
              "http://mybatis.org/dtd/mybatis-3-config.dtd">
            <configuration>
            	<settings>
            		<setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString" />
            		<setting name="lazyLoadingEnabled" value="true" />
            		<setting name="defaultExecutorType" value="SIMPLE" />
            		<setting name="defaultStatementTimeout" value="25000" />
            	</settings>
            </configuration>
            Last edited by eviljan; Jan 15th, 2013, 10:02 PM.

            Comment

            Working...
            X