java.lang.OutOfMemoryError: пространство кучи Java - как сэкономить память? - PullRequest
3 голосов
/ 17 июля 2011

Я пытаюсь настроить потребление памяти моим приложением JSF, устанавливая аргументы JVM, потому что я получаю из-за ошибки памяти.

Я могу увеличить кучу памяти и перезагружать сервер два раза в день, но это не решение ...

Аргументы JVM :

-XX:+UseConcMarkSweepGC
-XX:+UseParNewGC
-XX:+CMSClassUnloadingEnabled
-XX:+CMSParallelRemarkEnabled
-XX:CMSInitiatingOccupancyFraction=30
-XX:+CMSIncrementalMode
-XX:+CMSIncrementalPacing
-XX:ParallelCMSThreads=2
-XX:+UseCMSCompactAtFullCollection
-XX:+DisableExplicitGC
-XX:MaxHeapFreeRatio=70
-XX:MinHeapFreeRatio=40
-XX:MaxTenuringThreshold=30
-XX:NewSize=512m
-XX:MaxNewSize=512m
-XX:SurvivorRatio=2
-XX:PermSize=150m
-Xms1024m 
-Xmx1024m

Кажется, все работает нормально, постоянное пространство составляет 0 МБ, пространство eden непрерывно очищается, но пространство выживших продолжает расти, и когда оно достигает своего предела, объект перемещается в постоянное пространство и никогда не освобождается.И через пол дня запуска приложения вылезла ошибка нехватки памятиПоэтому я должен запланировать автоматический перезапуск сервера Tomcat.

enter image description here

Поэтому я думаю, что в моем приложении должна быть какая-то проблема, потому что его потребление памяти слишком велико для такого маленького приложения (около тысячи перемещений в базе данных в день).

Есть часть моего кода:

Bean.java

/* save datalist */
public void save() 
{
  session = DaoSF.getSessionFactory.openSession();
  try
  {
    Dao.save(dataList);
  }
  catch  (Exception e) {...}
  finally
  {
    session.close();
  }
}

Dao.java

public static void save(List<? extends Object> dataList)
{  
  for (Object dataItem : dataList) 
  {  
    save(dataItem);  
  }  
}  
public static void save(Object dataItem) 
{ 
  try 
  { 
    Transaction tx = session.beginTransaction();  
    session.save(dataItem);  
    tx.commit();  
  }  
  catch(Exception e) {....}
}

DaoSF.java

public class DaoSF implements Serializable
{
  private static final long serialVersionUID = 1L;
  private static SessionFactory sessionFactory;
  private static Session hibSession;

  private static synchronized void initSessionFactory
  {
    Configuration config = new Configuration();
    config.configure("hibernate.cfg.xml");
    sessionFactory = config.buildSessionFactory();
    hibSession = sessionFactory.getCurrentSession();
  }

  public static SessionFactory getSessionFactory 
  {
    initSessionFactory;
    return sessionFactory;
  }

  public static Session getSession() 
  {
    return hibSession;
  }
}

Не могли бы вы сказать, каковы наилучшие методы сохранения (обновления, удаления) объекта в базе данных, чтобы сохранить сохраненный объектне остаться в памяти?

Ответы [ 3 ]

4 голосов
/ 17 июля 2011

Крайне маловероятно, что ваши проблемы с памятью напрямую связаны с чем-либо, что вы делаете в отношении сохранения / удаления / обновления объектов в вашей базе данных.Пространство PermGen обычно не используется ни для каких объектов уровня пользователя.Он используется для вещей, которые предназначены для никогда освобождения, таких как определения классов, внутренние биты состояния JVM и тому подобное.

Если бы возникла проблема с управлением объектами данных, вы бы увидели OutOfMemoryError с жалобой на отсутствие свободного места в куче.Но чтобы ответить на ваш вопрос, вообще говоря, ваши объекты данных будут собираться мусором на следующем этапе сбора мусора, который запускается после того, как они выходят из области видимости (это означает, что у вас больше нет ссылок на них).Я подозреваю, что вы уже справляетесь с этим нормально, так как у вас нет проблем OutOfMemoryError.

Если у вас недостаточно PermGen места, это может быть связано с тем, что ваше приложение использует большое количество библиотек.К сожалению, единственный способ исправить это - увеличить размер PermGen, например:

-XX:PermSize=256m

Обратите внимание, что это существенно уменьшит объем пространства кучи, доступного дляваше приложение, поэтому обычно целесообразно увеличить общее выделение памяти JVM на соответствующую величину, например:

-Xmx1130m

Попробуйте и посмотрите, работает ли она лучше для вас.

3 голосов
/ 17 июля 2011

Попробуй это. Это еще не идеально, но я думаю, что вы должны избавиться от статического атрибута сеанса в Дао. См. Документы гибернации: http://docs.jboss.org/hibernate/envers/3.5/javadocs/org/hibernate/Session.html:

Предполагается, что разработчики не будут обеспечивать безопасность потоков. Вместо этого каждый поток / транзакция должен получить свой собственный экземпляр из SessionFactory.

Вы также можете получить сессию внутри Dao , так что Bean не имеет никаких знаний о базовых механизмах персистентности, но я не хотел так сильно менять.

Bean.java

/* save datalist */
public void save() {
    Session session = nlul;
    try {
        session = DaoSF.getSessionFactory.openSession();
        /* one instance per call, 
         * ready for garbage collection after leaving this method
         */
        Dao mydao = new Dao(session);
        mydao.save(dataList);
    } catch  (Exception e) {...
    } finally {
        if (sessioN != null)
            session.close();
    }
}

Dao.java

private Session mysession = null;

public Dao(Session mysession) {
    this.mysession = mysession;
}

public void save(List<? extends Object> dataList) {  
    for (Object dataItem : dataList) {  
        save(dataItem);
    }  
}  

public void save(Object dataItem) { 
    try  { 
        Transaction tx = session.beginTransaction();  
        this.mysession.save(dataItem);  
        tx.commit();  
    }  
    catch(Exception e) {....}
}
2 голосов
/ 17 июля 2011

Если у вас есть «PermGen: Out of Memory», он не очень связан с каким-либо Эдемом, выжившим или местом пребывания.

Это происходит в permgen, части "Non-Heap", которая связана с -XX: PermSize = 150m. Попробуйте увеличить его.

Или, в противном случае, может произойти утечка памяти в JSP / компиляторе сервлетов / classloader / spring, что также может занять классы выделенной памяти. Попытайтесь уменьшить количество классов (не instance0, использующий прокси-серверы или сгенерированные AOP классы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...