Bor*_*oro 5 java memory ibatis mybatis
我在NetBeans Profiler中观察到,在执行查询后,Surviving Generations继续增加:
@Select("SELECT * FROM ais_dynamic WHERE rep_time >= #{from} AND rep_time <= #{to} AND ais_system = #{sys}")
@Options(useCache=false,fetchSize=8192)
List<AisDynamic> getRecords(
@Param("from") Timestamp from,
@Param("to") Timestamp to,
@Param("sys") int sys);
Run Code Online (Sandbox Code Playgroud)
就好像列表中的对象永远不会被释放,尽管它们没有被其他地方使用,并且应该在后台线程运行查询并处理其结果时死亡.
以下是NetBeans Profiler返回的实时结果:

我的问题:
Options虽然这没有阻止内存泄漏?如果需要什么,请告诉我们将提供什么.
更新:
经过更多的测试后,我更担心问题在于MyBatis持有对检索结果的引用,因此它们不会随着时间的推移而被垃圾收集.在完成20次查询调用之后,等待我即使在30分钟后也没有观察到垃圾回收.我所做的只是调用方法:List<AisDynamic> adList = mapper.getRecords(from, to, sys);
我周末测试了它,看来我解决了这个问题。感谢@partlov 的建议,尽管这不是解决方案,但它让我再次测试问题,并且发现了真正的问题。
问题是我负责处理用户查询请求的客户端正在堆积线程(正在执行查询)。run()由于当我对客户端进行压力测试时,请求非常频繁地出现,因此当上一个查询未完成时,下一个查询就会开始,即使我通过在查询方法中设置和检查标志来取消它们。当查询会话仍在与数据库对话时,例如当选择有超过 30k 个结果时,就会出现这种情况。因此,尽管取消标志已提出,但尚未检查,因为查询正在从数据库检索结果。这对于下一个查询启动来说是足够的时间,因此如果它也有很多结果,客户端就会堆积线程,实际上会消耗越来越多的内存。
由于(据我所知)似乎无法取消与数据库对话的会话(例如选择查询)(在MyBatis),因此我必须自己实现一种保护机制。我在客户端中实现的机制可确保在前一个查询(为同一用户执行)完成之前不会启动下一个查询。因此,现在查询会在退出其run()方法时通知客户端,然后才可能启动同一用户的下一个查询。
更新我从经验中了解到,中止/取消长检索事务的唯一且有点肮脏的方法(根据我的口味)是通过调用事务使用的实例close()的方法。SqlSession这将导致异常(下面的示例),必须按预期捕获和处理该异常。
org.apache.ibatis.exceptions.PersistenceException:
### Error querying database. Cause: java.lang.NullPointerException
### The error may exist in YourMapper.java (best guess)
### The error may involve methodOfTheHandlerInvolved
### The error occurred while handling results
### SQL: sqlOfYourQuery
### Cause: java.lang.NullPointerException
... (and a trace follows) ...
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2673 次 |
| 最近记录: |