垃圾收集似乎不适用于java

时间:2016-03-22 06:01:51

标签: java garbage-collection out-of-memory batch-insert

以下方法有2个for循环。 Firstloop迭代36000次,内部forloop迭代24次,因此记录插入的总数将为864000。 代码执行运行将近3.5小时并终止。(记录插入失败) 会话闭包和事务提交仅在外部for循环结束后进行。发现执行期间RAM消耗接近6.9GB

@SuppressWarnings("unchecked")


public void createBRResults() {

    List<BusinessRules> businessRuleList = null;
    Organization organization = null;
    Brresults brresults = null;
    Criteria criteria = null;
    Criteria newCriteria = null;
    String brStatus = "Live";
    Date date = new Date();
    Session session = sessionFactory.openSession();
    Transaction transaction = null;
    try {
        if (callInfos == null) {
            callInfos = getEntities(CallInfo.class);
        }
        for (CallInfo callInfo : callInfos) {
            transaction = session.beginTransaction();
            criteria = session.createCriteria(BusinessRules.class);
            criteria.createCriteria("businessGoals").add(
                    Restrictions.eq("category", callInfo.getCategory()));
            businessRuleList = criteria.list();
            organization = callInfo.getOrganization();
            for (BusinessRules businessRule : businessRuleList) {
                brresults = new Brresults();
                brresults.setBusinessRule(businessRule);
                brresults.setCallInfo(callInfo);
                brresults.setCreatedDate(date);
                brresults.setModifiedDate(date);
                brresults.setOrganization(organization);
                brresults.setBrrStatus(brStatus);
                brresults.setBrrValue(Math.random() < 0.5 ? 0 : 1);
                session.save(brresults);
                brresults = null;
            }
            criteria = null;
            organization = null;
            businessRuleList = null;
            session.flush();
            session.clear();
            transaction.commit();
            System.gc();
        }
    } catch (Exception ex) {
        ex.printStackTrace();
    } finally {
        session.close();
    }
}

我附加了最后几行GC日志以指示内存分配

17034.595:[完整GC(人类工效学)[PSYoungGen:979968K-> 979964K(1862144K)] [ParOldGen:5576158K-> 5576158K(5576192K)] 6556126K-> 6556123K(7438336K),[Metaspace:23195K-> ; 23195K(1071104K)],2.1041939秒] [时间:用户= 8.61 sys = 0.00,实际= 2.11秒]

17036.699:[全GC(人类工效学)[PSYoungGen:979968K-> 979964K(1862144K)] [ParOldGen:5576158K-> 5576158K(5576192K)] 6556126K-> 6556123K(7438336K),[Metaspace:23195K-> ; 23195K(1071104K)],1.5930338秒] [时间:用户= 9.39 sys = 0.00,实际= 1.59秒] 17038.292:[全GC(人类工效学)[PSYoungGen:979968K-> 979964K(1862144K)] [ParOldGen:5576158K-> 5576158K(5576192K)] 6556126K-> 6556122K(7438336K),[Metaspace:23195K-> 23195K( 1071104K)],1.9376959秒] [时间:用户= 8.51 sys = 0.00,真实= 1.94秒]

17040.230:[全GC(人类工效学)[PSYoungGen:979968K-> 830418K(1862144K)] [ParOldGen:5576158K-> 5576027K(5576192K)] 6556126K-> 6406445K(7438336K),[Metaspace:23196K-> ; 23196K(1071104K)],2.9929302 secs] [次:用户= 17.97 sys = 0.00,real = 3.00 secs]

堆  PSYoungGen总计1862144K,使用889367K [0x0000000715d80000,0x00000007bdc80000,0x00000007c0000000)

伊甸园空间979968K,90%使用[0x0000000715d80000,0x000000074c205e48,0x0000000751a80000)   来自space 882176K,0%使用[0x0000000787f00000,0x0000000787f00000,0x00000007bdc80000)   空间885760K,0%使用[0x0000000751a80000,0x0000000751a80000,0x0000000787b80000)  ParOldGen总计5576192K,使用5576027K [0x00000005c1800000,0x0000000715d80000,0x0000000715d80000)   对象空间5576192K,99%使用[0x00000005c1800000,0x0000000715d56d38,0x0000000715d80000)  Metaspace使用23223K,容量23502K,承诺24064K,保留1071104K   类空间使用2443K,容量2537K,承诺2560K,保留1048576K

但如果我关闭会话并每24次重复再次打开,则记录插入成功,所需时间为55分钟。但RAM利用率约为3GB。

为什么垃圾收集没有正常发生?代码中有哪些错误?

1 个答案:

答案 0 :(得分:4)

Session正在累积对您触摸的所有对象的引用,因为如果您在同一会话中要求它两次,它必须返回完全相同的对象。您需要定期关闭它以允许它丢弃其上下文。