首页 新闻 会员 周边 捐助

spring声明式事务无法关闭session

0
悬赏园豆:120 [待解决问题]

目前有一已上线试运行项目,Spring+Struts2+Hibernate,外加Quartz框架跑定时任务,Hibernate lazy="true",自然用上了openSessionInViewFilter,Ehcache二级缓存缓存只读的一小部分数据,应用服务器采用Tomcat6,物理服务器Linux+4G RAM,现在情况是,JVM内存最大配了2G,查看tomcat list applications 默认session有效时间(30分)内也就30-50个session,server status 每过半天,free memory就剩100多M了,甚至就个位数了,GC也仅能回收几十M,必须重启,jmap取得堆转储文件,用Eclipse Memoery Analyzer分析,内存泄漏,其中80%多是被连接占用,如下:

89 instances of "org.hibernate.impl.SessionFactoryImpl", loaded by "org.apache.catalina.loader.WebappClassLoader @ 0x8bead108" occupy 854,135,176 (82.98%) bytes.
These instances are referenced from one instance of "java.util.HashMap$Entry[]", loaded by "<system class loader>"


// Class Name Ref. Objects Shallow Heap Ref. Shallow Heap Retained Heap
org.quartz.simpl.SimpleThreadPool$WorkerThread @ 0xb65524f8 scheduler_Worker-7 Busy Monitor, Thread 89 120 11,392 392
contextClassLoader org.apache.catalina.loader.WebappClassLoader @ 0x8bead108 89 168 11,392 5,814,616
classes java.util.Vector @ 0x8ca08598 89 24 11,392 20,520
elementData java.lang.Object[5120] @ 0x8cd19528 89 20,496 11,392 20,496
[2268] class org.hibernate.impl.SessionFactoryObjectFactory @ 0xed5dbd68 89 24 11,392 2,896
INSTANCES org.hibernate.util.FastHashMap @ 0x8c904918 89 16 11,392 2,720
map java.util.HashMap @ 0xc8f562a8 89 40 11,392 2,704
table java.util.HashMap$Entry[128] @ 0xc8f562d0 89 528 11,392 2,664
[17] java.util.HashMap$Entry @ 0xc8f565a0 » 4 24 512 96
[55] java.util.HashMap$Entry @ 0xc8f567b0 » 4 24 512 96
[109] java.util.HashMap$Entry @ 0xc8f56a98 » 4 24 512 96
[107] java.util.HashMap$Entry @ 0xc8f56a80 » 3 24 384 72
[0] java.util.HashMap$Entry @ 0xc8f564e0 » 2 24 256 48
......
[25] java.util.HashMap$Entry @ 0xc8f565e8 » 1 24 128 24
Total: 25 of 66 entries 89 1,584 11,392


好像Quartz的嫌疑最大,在proxool管理页面,可以看到我初始连接开了12个,最大连接数为128个,当其中一个quartz任务线程启动,而事实上任务本身只是发了一条语句而已,活动连接数居然一下子就到68个了,关键是任务都是受控于Spring声明式事务内的啊,不需要我们显式的开关吧,吐血了,下面再附上applicationContext.xml:


// <bean id="DataSource" class="org.logicalcobwebs.proxool.ProxoolDataSource">
<property name=
"driver" value="oracle.jdbc.driver.OracleDriver"></property>
<property name=
"driverUrl" value="jdbc:oracle:thin:@172.168.1.144:1521:orcl10G"></property>
<property name=
"user" value="aaa"></property>
<property name=
"password" value="xsgldb"></property>
<property name=
"alias" value="xsgldb_pool" />
<property name=
"prototypeCount" value="4" />
<property name=
"maximumConnectionCount" value="128" />
<property name=
"minimumConnectionCount" value="12" />
<property name=
"simultaneousBuildThrottle" value="128" />
<property name=
"maximumActiveTime" value="300000" />
<property name=
"houseKeepingSleepTime" value="99000" />
<property name=
"houseKeepingTestSql" value="select 1 from dual" />
</bean>
<bean id=
"sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name=
"dataSource">
<ref bean=
"DataSource" />
</property>
<property name=
"hibernateProperties">
<props>
<prop key=
"hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop>
<prop key=
"hibernate.show_sql">false</prop>

<!-- 指定Hibernate持久化操作的批操作大小 -->
<prop key=
"hibernate.jdbc.batch_size">30</prop>
<prop key=
"hibernate.jdbc.fetch_size">50</prop>
<prop key=
"hibernate.max_fetch_depth">2</prop>
<prop key=
"hibernate.default_batch_fetch_size">10</prop>
<prop key=
"hibernate.cache.use_query_cache">true</prop>
<prop key=
"hibernate.cache.use_second_level_cache">true</prop>
<prop key=
"hibernate.cache.provider_class">net.sf.ehcache.hibernate.SingletonEhCacheProvider</prop>
<prop key=
"hibernate.connection.release_mode">auto</prop>
<prop key=
"hibernate.transaction.flush_before_completion">true</prop>
<prop key=
"hibernate.query.factory_class">org.hibernate.hql.ast.ASTQueryTranslatorFactory </prop>
</props>
</property>
<property name=
"mappingDirectoryLocations">
<list>
<value>classpath:/cn/bbb/aaa/entity</value>
</list>
</property>
</bean>
<bean id=
"transactionManager"
class=
"org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name=
"sessionFactory" ref="sessionFactory" />
</bean>

<tx:advice id=
"txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name=
"find*" propagation="REQUIRED" read-only="true"/>
<tx:method name=
"pagedQuery*" propagation="REQUIRED" read-only="true"/>
<tx:method name=
"save*" propagation="REQUIRED" />
<tx:method name=
"delete*" propagation="REQUIRED" />
<tx:method name=
"merge*" propagation="REQUIRED" />
<tx:method name=
"update*" propagation="REQUIRED" />
<tx:method name=
"add*" propagation="REQUIRED" />
<tx:method name=
"*" propagation="REQUIRED" />
</tx:attributes>
</tx:advice>

<aop:config>
<aop:pointcut id=
"interceptorPointCuts"
expression=
"execution(* cn.bbb.aaa.*.service.*.*(..))" />
<aop:advisor advice-ref=
"txAdvice"
pointcut-ref=
"interceptorPointCuts" />
</aop:config>
<bean id=
"simpleThreadPoolTaskExecutor"
class=
"org.springframework.scheduling.quartz.SimpleThreadPoolTaskExecutor">
<property name=
"makeThreadsDaemons" value="true"/>
<property name=
"threadCount" value="3" />
<property name=
"threadPriority" value="5" />
<property name=
"threadsInheritContextClassLoaderOfInitializingThread" value="true"/>
<property name=
"threadNamePrefix" value="quartz-simpleThreadPoolTaskExecutor"/>
<property name=
"waitForJobsToCompleteOnShutdown" value="true" />
</bean>
<bean id=
"scheduler" lazy-init="false" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name=
"taskExecutor" ref="simpleThreadPoolTaskExecutor"/>
<property name=
"triggers">
<list>
<ref bean=
"expiredPrepareTrigger"/>
</list>
</property>
</bean>

 

这种情况我能如何解决这个麻烦呢?还请高手指点迷津

freeflysky的主页 freeflysky | 初学一级 | 园豆:10
提问于:2010-11-24 14:10
< >
分享
所有回答(2)
0

很长,看了很久,有点累。。。。

Tester Chen | 园豆:1690 (小虾三级) | 2010-11-25 08:11
问题后来已解决,原因并非spring事务造成,而是其中有需要调用存储过程的代码,以读取配置文件的方式获取数据源,以取得连接资源,在读配置文件时重复加载而导致内存泄漏,结果放弃读配置文件的方式,问题就解决了
支持(0) 反对(0) freeflysky | 园豆:10 (初学一级) | 2011-01-14 16:29
0

你好,这个问题的解决方法能具体说明一下吗?所谓的读取配置文件取得连接资源,是读取的什么配置文件?

希望能提供一个具体的解决方法,谢谢

笑雨田 | 园豆:205 (菜鸟二级) | 2012-01-04 15:34
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册