утечки постоянной памяти Java

#java #jpa #memory-leaks

#java #jpa #утечки памяти

Вопрос:

У меня в таблице 1 МЛН строк, и я хочу получить их все. Но когда я пытаюсь получить все строки с помощью jpa путем разбивки на страницы, я получаю ошибку java heap. Вы думаете, я что-то упускаю? Любой совет

 int counter = 0;
while (counter >= 0) {
   javax.persistence.EntityManager em = javax.persistence.Persistence
     .createEntityManagerFactory("MyPU")
     .createEntityManager();

   Query query = em.createQuery("select m from mytable m");
   java.util.Collection<MyEntity> data = query
          .setFirstResult(counter).setMaxResults(1000).getResultList();
   for(MyEntity yobj : data){
            System.out.println(obj);
   }
   counter  = 1000;
   data.clear();
   em.clear();
   em.close();
}
  

Комментарии:

1. Вы пытались увеличить максимальный размер кучи с помощью -Xmx? Смотрите: javahowto.blogspot.com/2006/06 /…

Ответ №1:

Поскольку вы все равно используете собственный SQL, не можете ли вы указать LIMIT :counter, 1000 (или ROWNUM BETWEEN :counter AND 1000 при использовании Oracle) непосредственно в вашем SQL-операторе?

Комментарии:

1. Ну, я использую mysql, где мы можем указать ограничение, но это не разрешено JPA. JPA предоставляет механизм разбиения на страницы с помощью set firstResutl и установки максимального результата, который работает нормально, но когда счетчик достигает 250 000, он выдает исключение кучи

2. Да, некоторые реализации JPA выполняют подкачку «в памяти» вместо того, чтобы позволить базе данных делать это, что, конечно, бессмысленно. Работает ли это с EntityManager.createNativeQuery() ?

3. единственный способ — использовать собственный запрос для разбивки на страницы, чтобы предотвратить утечки памяти. это работает благодаря всем

Ответ №2:

Обратите внимание, что вы создаете новый экземпляр EntityManagerFactory на каждой итерации, но не закрываете его. Возможно, было бы лучше использовать вместо этого одну фабрику:

 int counter = 0;
EntityManagerFactory emf = javax.persistence.Persistence.createEntityManagerFactory("MyPU");      
while (counter >= 0) {
    javax.persistence.EntityManager em = emf.createEntityManager(); 
    ...
}
  

Комментарии:

1. Я попытался реализовать, как вы предложили, но все равно это не освобождает память.