Java - Предотвращение ошибки памяти кучи Java с помощью инфраструктуры Swing и абстрактных классов - PullRequest
1 голос
/ 19 марта 2012

Очень надеюсь, что вы можете помочь.Я создал приложение для управления запасами с помощью инфраструктуры Java Swing.Это приложение имеет 1 абстрактный класс с именем GUIRules, который расширяет JPanel, реализует actionListener, и 8 различных классов, которые расширяют GUIRules для представления каждого экрана.

public abstract class GUIRules extends JPanel implements ActionListener{}

public class login extends GUIRules {}

Дело в том, что все эти 8 классов имеют много общего;поэтому я решил предоставить каждому из них функциональность по умолчанию.

При переходе к каждому экрану все загружается нормально;Тем не менее, я в конечном итоге сталкиваюсь с ошибкой памяти кучи Java.Это метод, который позволяет менять экран:

    /**
 * When switching between GUI screens, declare new GUI within parameters
 * @param panel 
 */
public void changePanel(JPanel panel){
    this.removeAll();   
    this.add(panel); 
    validate();
    setVisible(true);
}

this.removeAll () должен удалить все компоненты, освобождая тем самым память.Все слушатели действий добавляются в конструкторы всех 8 экранов;так что это также должно быть устранено при вызове этой функции.

Это приложение также использует изображения.

Абстрактный класс (GUIrules) вызывает paintComponent () для загрузки фонового изображения:

    /**
 * Paint background, menu and logo images onto this class.
 */
public void paintComponent(Graphics g) 
{
    super.paintComponent(g);
    g.drawImage(image.mainImg, 0, 0,getWidth(),getHeight(),null);
    g.drawImage(image.menuImg, 0, 30, getWidth(), 80, null); 
    g.drawImage(image.logoImg, 0, 33, null); g.setColor(Color.CYAN);
    g.drawString(SystemSession.user, 10, 20);
    g.drawString(SystemSession.status, 10, getHeight()-10);
    repaint();
}

Я использовал Runtime.gc () для сбора мусора неиспользуемых объектов, но особой разницы нет.Есть идеи?Большое спасибо.

Ответы [ 4 ]

1 голос
/ 21 марта 2012

Понятно, что у вас утечка памяти.Хотя это не показано в вашем коде, я предполагаю, что утечка вызвана вашими слушателями на основе

this.removeAll () должен удалить все компоненты, тем самым освободив память.Все слушатели действий добавляются в конструкторы всех 8 экранов;так что это также должно быть устранено при вызове этой функции.

Когда экземпляр класса A является слушателем, который присоединен к экземпляру B, экземпляр B будет сохранять сильныйссылка на слушателя, следовательно, сильная ссылка на A.Таким образом, удаление ссылок на A и сохранение ссылки на B гарантирует, что A не является GC-ed, поскольку на него строго ссылаются B.

В вашем случае, A это ваш GUIRules класс и B любой класс, к которому вы прикрепляете свой GUIListener.Вызов removeAll для контейнера, который используется для отображения вашего GUIRules, не позволяет GC этот экземпляр, когда он все еще присоединен в качестве слушателя к другому объекту, на который вы строго ссылаетесь.

Кроме этогоВы рассматривали возможность использования CardLayout для переключения между 8 панелями.Это сохранит 8 панелей в памяти, но избавит от необходимости каждый раз создавать новые (что, я полагаю, вы делаете сейчас, или вы не встретите исключение OoM)

1 голос
/ 19 марта 2012

Вы должны убедиться, что вы помещаете удалить все на EDT, иначе ваше приложение будет испытывать проблемы при возникновении.

   SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            this.removeAll();   
            this.add(panel); 
            validate();
            setVisible(true);
        }
   });
1 голос
/ 19 марта 2012

Короткий ответ - увеличьте максимальный размер кучи , используя опцию -Xmx .

Максимальный размер кучи, доступный для Java VM, может быть увеличен. Значение по умолчанию зависит от вашей системы, но вы можете увеличить его, учитывая объем памяти, доступной в системе, в которой вы запускаете приложение. Например, чтобы увеличить максимальный размер кучи до 1 ГБ, используйте что-то вроде:

java -Xmx1024M -jar yourapp.jar

Более длинный ответ - используйте профиль, чтобы узнать, сможете ли вы уменьшить использование памяти вашим приложением.

Существуют инструменты, которые позволят вам изучить использование памяти вашим приложением во время его работы. Это позволит вам увидеть, собираются ли объекты мусор так, как вы ожидаете, или у вас есть утечка памяти, из-за которой у вас заканчивается куча пространства.

0 голосов
/ 19 марта 2012

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

В случае утечки памяти вашего кода недостаточно (чтобы увидеть, в чем заключается настоящая проблема), в любом случае вам следует профилировать приложение, чтобы устранить проблему, см. Эту статью: http://java.dzone.com/news/how-fix-memory-leaks-java

если вашему приложению требуется больше памяти, просто увеличьте размер кучи:

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