我现在遇到了一个非常奇怪的Java GC问题,当我尝试在一个JFrame中创建一个按钮时,点击按钮会显示一个需要处理并显示一些图片、需要近200M内存的JDialog。但问题是,当我关闭对话框并重新打开它时,有时会导致java.lang.OutOfMemoryError错误(并非每次都出现)。
为了解决这个问题,我简化了这个问题并进行了一些实验,结果让我更加困惑。我的“实验”中使用的代码如下所示:当我在一个框架中点击一个按钮时,我为一个整数数组分配了160M内存,并显示了一个对话框。但是,如果我关闭对话框并重新打开它,就会出现OutOfMemoryError错误。我调整了代码,结果如下:
现在问题是,当我点击按钮并尝试创建一个整数数组时,我上次创建的整数数组肯定可以被Java的GC收集。那么为什么会出错呢?
另外,我用来启动JVM的参数是“java -Xmx256m”。
为了解决这个问题,我简化了这个问题并进行了一些实验,结果让我更加困惑。我的“实验”中使用的代码如下所示:当我在一个框架中点击一个按钮时,我为一个整数数组分配了160M内存,并显示了一个对话框。但是,如果我关闭对话框并重新打开它,就会出现OutOfMemoryError错误。我调整了代码,结果如下:
- If I don’t create the dialog and show it, no memory problem.
- If I add a windowsCloseListener which invoke System.gc() to the dialog, no memory problem.
If I invoke System.gc() in the run() method, memory problem shows.
public class TestController { int[] tmp; class TDialog extends JDialog { public TDialog() { super(); this.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); // If I uncommment this code, OutOfMemoryError seems to dispear in this situation // But I'm sure it not a acceptable solution /* this.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.out.println("windowsclose"); TDialog.this.dispose(); System.gc(); } }); */ } } TDialog dia; public void run() { // If I do System.gc() here, OutOfMemoryError still exist // System.gc(); tmp = new int[40000000]; for (int i = 0; i < tmp.length; i += 10) tmp[i] = new Random().nextInt(); dia = new TDialog(); dia.setVisible(true); } public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { @Override public void run() { final JFrame frame = new JFrame("test"); frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); frame.setLocationRelativeTo(null); frame.setSize(200, 200); JButton button = new JButton("button"); button.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { TestController controller = new TestController(); controller.run(); controller = null; } }); frame.add(button); frame.setVisible(true); } }); } }
现在问题是,当我点击按钮并尝试创建一个整数数组时,我上次创建的整数数组肯定可以被Java的GC收集。那么为什么会出错呢?
另外,我用来启动JVM的参数是“java -Xmx256m”。
dispose()
方法来释放对话框,这样会怎么样呢? - Hovercraft Full Of Eels