私有方法调用的垃圾收集

时间:2012-02-16 13:12:56

标签: java memory-management garbage-collection

我的java应用程序中存在内存使用问题,对于我的生活,我无法理解为什么垃圾收集器没有将其整理出来。代码如下:

public void foo() {
    for(int i=0; i<50000; i++) {
        bar(i);
    }
}

private void bar(int i) {
    LargeObject o = new LargeObject();
    ...
    dao.save(o);
}

我的问题是LargeObject的实例没有被垃圾收集 - 为了识别这个我用jprofiler进行了分析并查看了堆。 LargeObject实例永远不会被类变量引用,实际上它们不会在bar()之外的任何地方引用。我抓住我的稻草,但这可能与交易的开始/结束有关吗?我尝试将bar()更改为公开,并使用Propogation.REQUIRES_NEW进行注释,并将foo()上的注释更改为Propogation.NEVER,但无效。

dao中的代码如下所示:

public void save(LargeObject o) {
    hibernateTemplate.getSessionFactory().getCurrentSession().saveOrUpdate(o);
}

垃圾收集肯定会在我看到它在jprofiler中的活动时运行。 foo()大约需要30分钟,bar()大约需要36分钟,垃圾收集大约每60秒一次。

要回答这个问题,为什么我确定它们不是垃圾收集 - 系统中没有任何内容引用LargeObject但我在堆上看到它们的实例随着foo()的执行而增加。

2 个答案:

答案 0 :(得分:4)

显然,您的JPA提供程序(或隐藏在dao.save()后面的任何内容)都会引用它们。你确实让引用在外面,因此你对它的控制就会丢失。无论你是采用私人/公共方法进行操作都无关紧要。

您可能想要分享有关此“DAO”的更多信息。

答案 1 :(得分:2)

我要添加@MaDa的答案,循环可能会导致必须缓存所有Large Objects个实例的唯一会话的负担。您应该考虑:保存后刷新会话,或者为每个LargeObject使用新会话或清除会话如果它们不相关

阅读Batch Processing部分可能有助于您了解问题