У меня есть приложение, которому нужно открыть несколько JFrames (это просмотрщик журналов, а иногда вам нужно увидеть кучу журналов в отдельных окнах для сравнения).JFrame никогда не собирает мусор
Похоже, что JVM (обновление Java 8 на OS X) содержит значительную ссылку на JFrame, что мешает ему собирать мусор и в конечном итоге приводит к выбросу OutOfMemoryError.
Чтобы устранить проблему, выполните эту проблему с максимальным размером кучи 200 мегабайт. Каждый раз, когда открывается окно, он потребляет 50 мегабайт оперативной памяти. Откройте три окна (используя 150 мегабайт оперативной памяти). Затем закройте три окна (которые вызывают dispose), которые должны освободить память. Затем попробуйте открыть четвертое окно. Вызывается OutOfMemoryError, и четвертое окно не открывается.
Я видел другие ответы, в которых говорилось, что память будет автоматически выпущена, когда это необходимо, чтобы избежать иссякновения, но это, похоже, не происходит.
package com.prosc.swing;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.NumberFormat;
public class WindowLeakTest {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
JFrame launcherWindow = new JFrame("Launcher window");
JButton launcherButton = new JButton("Open new JFrame");
launcherButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JFrame subFrame = new JFrame("Sub frame") {
private byte[] bigMemoryChunk = new byte[ 50 * 1024 * 1024 ]; //50 megabytes of memory
protected void finalize() throws Throwable {
System.out.println("Finalizing window (Never called until after OutOfMemory is thrown)");
super.finalize();
}
};
subFrame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
subFrame.add(new JLabel("Nothing to see here"));
subFrame.pack();
subFrame.setVisible(true);
System.out.println("Memory usage after new window: " + getMemoryInfo());
}
});
launcherWindow.add(launcherButton);
launcherWindow.pack();
launcherWindow.setVisible(true);
new Timer(5000, new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.gc();
System.out.println("Current memory usage after garbage collection: " + getMemoryInfo());
}
}).start();
}
});
}
public static String getMemoryInfo() {
NumberFormat numberFormat = NumberFormat.getNumberInstance();
return "Max heap size is " + numberFormat.format(Runtime.getRuntime().maxMemory()) + "; free memory is " + numberFormat.format(Runtime.getRuntime().freeMemory()) + "; total memory is " + numberFormat.format(Runtime.getRuntime().totalMemory());
}
}
Javadoc Java SE 7 Window.dispose: «Окно и его подкомпоненты можно отображаемые вновь восстанавливая собственные ресурсы с последующим вызовом для упаковки или шоу «. Это может быть причиной того, что ссылка все еще присутствует. – mm759
Возможно дубликат: http://www.stackoverflow.com/questions/7376993/does-disposing-a-jframe-cause-memory-leakage. Вы согласны? – mm759
Это почти такой же вопрос - я не нашел удовлетворительного ответа. Мне нужно несколько окон, и это похоже на ошибку, которую разработчик несет ответственность за очистку содержимого окна после вызова функции dispose(). Я надеялся, что образец кода может получить лучший ответ. –