Hibernate/Spring应用StatefulPersistenceContext内存占用过高排查
基于Hibernate+Spring应用的内存溢出问题排查求助
我有一个基于Hibernate和Spring的应用,处理中等规模数据集(约300万条记录)时出现内存不足问题。用Eclipse Memory Analyser分析内存转储后发现,StatefulPersistenceContext除了持有对象本身,还在内存中保存了一份记录副本,直接导致内存使用量翻倍。
我能通过以下小规模工作流复现问题:
- 从文件向数据库插入约40万条Fruit记录
- 从数据库获取所有Fruit,查找互补项创建约15万条包含两个Fruit的Basket记录
- 检索所有Fruit和Basket数据并保存到文件
问题出在最后一步,堆转储显示StatefulPersistenceContext在内存中保存了数十万条Fruit,和为保存文件检索的Fruit重复。
我已经尝试过以下方案,但都没解决StatefulPersistenceContext内存占用过高的问题:
- 在查询中添加
QueryHints.READ_ONLY(加在getAll方法上) - 在带readOnly属性的Transaction中执行查询
请问还有哪些需要排查的点?
相关类/查询示例
ShoppingService 接口
public interface ShoppingService { public void createBaskets(); public void loadFromFile(ObjectInput input); public void saveToFile(ObjectOutput output); }
ShoppingServiceImpl 实现类
@Service public class ShoppingServiceImpl implements ShoppingService { @Autowired private FruitDAO fDAO; @Autowired private BasketDAO bDAO; @Override public void createBaskets() { bDAO.add(Basket.generate(fDAO.getAll())); } @Override public void loadFromFile(ObjectInput input) { SavedState state = ((SavedState) input.readObject()); fDAO.add(state.getFruits()); bDAO.add(state.getBaskets()); } @Override public void saveToFile(ObjectOutput output) { output.writeObject(new SavedState(fDAO.getAll(), bDAO.getAll())); } public static void main(String[] args) throws Throwable { ShoppingService service = null; try (ObjectInput input = new ObjectInputStream(new FileInputStream("path\\to\\input\\file"))) { service.loadFromFile(input); } service.createBaskets(); try (ObjectOutput output = new ObjectOutputStream(new FileOutputStream("path\\to\\output\\file"))) { service.saveToFile(output); } } }
Fruit 实体类
@Entity public class Fruit { @Id @GeneratedValue(strategy = GenerationType.SEQUENCE) private Long id; private String name; // ~ 200 string fields }
FruitDAO 接口
public interface FruitDAO { public void add(Collection<Fruit> elements); public List<Fruit> getAll(); }
JPAFruitDAO 实现类
@Repository public class JPAFruitDAO implements FruitDAO { @PersistenceContext private EntityManager em; @Override @Transactional() public void add(Collection<Fruit> elements) { elements.forEach(em::persist); } @Override public List<Fruit> getAll() { return em.createQuery("FROM Fruit", Fruit.class).getResultList(); } }
Basket 实体类
@Entity public class Basket { @Id @GeneratedValue(strategy = GenerationType.SEQUENCE) private Long id; @OneToOne @JoinColumn(name = "arow") private Fruit aRow; @OneToOne @JoinColumn(name = "brow") private Fruit bRow; public static Collection<Basket> generate(List<Fruit> fruits) { // Some complicated business logic that does things return null; } }
BasketDAO 接口
public interface BasketDAO { public void add(Collection<Basket> elements); public List<Basket> getAll(); }
JPABasketDAO 实现类
@Repository public class JPABasketDAO implements BasketDAO { @PersistenceContext private EntityManager em; @Override @Transactional() public void add(Collection<Basket> elements) { elements.forEach(em::persist); } @Override public List<Basket> getAll() { return em.createQuery("FROM Basket", Basket.class).getResultList(); } }
SavedState 类
public class SavedState { private Collection<Fruit> fruits; private Collection<Basket> baskets; }
内容的提问来源于stack exchange,提问作者JackPGreen
相关产品推荐
相关产品推荐

