垃圾收集开销限制 - 休眠

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了垃圾收集开销限制 - 休眠相关的知识,希望对你有一定的参考价值。

我正在使用Hibernate查询我的mysql数据库,以查找特定旅程中的所有段。 (例如,从A-> D的旅程可能有段A-> B,B-> C,C-> D.)

我非常频繁地运行这个查询,它很快完成。数据库的索引方式是性能非常好。查询的代码如下:

public List<Segment> getSegmentsForUID(String trainUid) {
    Query segmentQuery = session.createQuery("select segment from Segment segment inner join segment.journey as journey where segment.journey " +
                                             "in (:journies) and journey.trainUid = '" + trainUid + "'");
    segmentQuery.setParameterList("journies", dailyJournies);
    queryCount++;
    return segmentQuery.getResultList();
}

其中dailyJournies在类的初始化中设置,并且永远不会再次更改。

我的问题是,在多次执行此查询后(通常在2,000到3,000个查询之间),我总是在Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded行上收到:return segmentQuery.getResultList();

由于在初始化之后没有触及此类的其他部分,并且因为异常总是抛在这一行上,所以我无法想象它在其他地方是一个问题。

经过一番挖掘后我最初的想法是Hibernate会话变得太大,所以我开始关闭并在每1000个查询后重新打开会话,但这没有任何区别。我也尝试使用以下代码:

Cache cache = session.getSessionFactory().getCache();
cache.evictAllRegions();

要手动清除会话缓存,但这也没有做任何事情。

有没有其他人遇到过这个或者有什么明显的东西让我失踪?

答案

我以前似乎没有找到合适的信息。

显然这是其他人也经历过的问题(https://github.com/ow2-proactive/scheduling/issues/2870)。

对于任何绊倒这个问题的人,我通过在我的hibernate配置文件中添加以下两行来修复它:

<property name="hibernate.query.plan_cache_max_size">16</property>
<property name="hibernate.query.plan_parameter_metadata_max_size">128</property>

这是GitHub中的建议。我认为问题源于保持会话和sessionFactory为许多查询打开。我猜这个问题也可以通过为每1,000个条目创建一个新的sessionFactory来解决,但这个解决方案似乎更清晰。

以上是关于垃圾收集开销限制 - 休眠的主要内容,如果未能解决你的问题,请参考以下文章

35垃圾回收器 — 概述

管理Java垃圾回收的五个建议

垃圾收集器

JVM 垃圾回收器

线程“main”中的异常java.lang.OutOfMemoryError:GWT应用程序中超出了GC开销限制

java虚拟机之垃圾收集器