我正在尝试处理重量级元素(图像)的收集。集合的大小在8000-50000个条目之间变化。但是由于某种原因,在处理了1800-1900个条目之后,我的程序因java.lang.OutOfMemoryError:Java堆空间而掉线。
以我的理解,每次调用session.getTransaction()。commit()程序都应该释放堆内存,但是看起来它永远不会发生。我做错了什么?这是代码:
private static void loadImages( LoadStrategy loadStrategy ) throws IOException { log.info( "Loading images for: " + loadStrategy.getPageType() ); Session session = sessionFactory.openSession(); session.setFlushMode( FlushMode.COMMIT ); Query query = session.createQuery( "from PageRaw where pageType = :pageType and pageStatus = :pageStatus and sessionId = 1" ); query.setString( "pageStatus", PageStatus.SUCCESS.name() ); query.setString( "pageType", loadStrategy.getPageType().name() ); query.setMaxResults( 50 ); List<PageRaw> pages; int resultNum = 0; do { session.getTransaction().begin(); log.info( "Get pages statring form " + resultNum + " position" ); query.setFirstResult( resultNum ); resultNum += 50; pages = query.list(); log.info( "Found " + pages.size() + " pages" ); for (PageRaw pr : pages ) { Set<String> imageUrls = new HashSet<>(); for ( UrlLocator imageUrlLocator : loadStrategy.getImageUrlLocators() ) { imageUrls.addAll( imageUrlLocator.locateUrls( StringConvector.toString( pr.getSourceHtml() ) ) ); } removeDeletedImageRaws( pr.getImages(), imageUrls ); loadNewImageRaws( pr.getImages(), imageUrls ); } session.getTransaction().commit(); } while ( pages.size() > 0 ); session.close(); }
你混淆了 冲洗 与 结算 :
刷新 会话将针对数据库执行所有待处理的语句(它将内存中状态与数据库状态同步);
清除 会话将清除会话(第一级)缓存,从而释放内存。
因此,您需要刷新 和 清除会话以恢复占用的内存。
除此之外,您还必须 禁用2级缓存 。否则,即使清除会话后,所有(或大多数)对象仍将保持可访问状态。