异常java.lang.OutOfMemoryError:树图

时间:2016-02-24 19:33:47

标签: java hibernate garbage-collection out-of-memory

从Hibernate查询加载行时,我一直收到java.lang.OutOfMemoryError: GC overhead limit exceeded

我已经尝试过多次增加内存,而且还会继续发生。我在日志中注意到它似乎指向了我使用TreeMap的方法。我想知道我是否错误地使用了这个导致内存不足的问题。

public List<Item> getProducts() {
    List<ProductListing> productListings = session.createCriteria(ProductListing.class)
    .createAlias("productConfiguration", "productConfiguration")
    .add(Restrictions.eq("productConfiguration.category", category))
    .add(Restrictions.eq("active", true))
    .add(Restrictions.eq("purchased", true)).list();

    Map<String, Item> items = new TreeMap<>();

    productListings.stream().forEach((productListing) -> {
        Item item = productListing.getItem();
        items.put(item.getName(), item);
    });

    return new ArrayList<>(items.values());
}
  • 将值传递给arraylist是否安全?

  • 我需要设置arraylist大小吗?

我只是想知道我是否做了一件非常糟糕的事情。它看起来是正确的,但内存异常另有说法。

1 个答案:

答案 0 :(得分:3)

我将此称为“加载世界” - 名称getProducts()(没有args)有点代码味道 - 因为您没有限制结果集大小,并且我们知道您的所有{ {1}}对象可能很大,有很多急切加载的依赖项(更不用说堆上的所有后备Hibernate对象)。

另一个大问题是,您将脱水实体昂贵地添加到Item,调用TreeMap和可能hashCode(),只是丢弃密钥并将值复制到新分配的equals()

暂且不考虑ArrayList的预先规模(正确,这不理想,虽然它应该只是缓慢),为什么ArrayList阶段?如果您需要进行聚合,为什么不让数据库更有效地执行此操作(例如通过TreeMap)并使用索引,而不是将其全部拉入地图以进行更慢的重新处理?至少,通过只返回唯一的GROUP BY name,您可以跳过地图阶段并直接复制到您的列表中(根据您的需要,甚至还有更轻量级的可能性)。

我强烈建议使用合适的Profiler进行测试。具体来说,它可以帮助您确定预先加载对堆大小的影响。可能只是将其关闭可能会使问题更易于管理。

但是,您还需要考虑代码的客户:谁真正需要那些Item全部?很可能没有人。