【发布时间】:2013-11-05 01:06:51
【问题描述】:
*当我尝试在JFrame中制作一个按钮时,我现在遇到了一个非常奇怪的java GC问题,当我单击该按钮时,它会显示一个需要处理和显示一些图像的JDialog,需要近200M记忆。但问题是当我关闭对话框并重新打开它时,有时会导致 java.lang.OutOfMemoryError。 (不是每次)
为了解决这个问题,我简化了这个问题并做了一些实验,这让我更加困惑。
我在“实验”中使用的代码如下所示。 当我单击一个框架中的按钮时,我为一个整数数组分配了 160M 内存,并显示了一个对话框,但是如果我关闭对话框并重新打开它,就会出现 OutOfMemoryError。 我调整了代码和结果是:
- 如果我不创建对话框并显示它,则没有内存问题。
- 如果我在对话框中添加一个调用 System.gc() 的 windowsCloseListener,则不会出现内存问题。
-
如果我在 run() 方法中调用 System.gc(),就会出现内存问题。
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 工作原理的文章。我认为如果java试图在堆中分配一些空间并且它没有足够的可用空间,java会做gc,如果一个对象不能通过“GC图”从gc根访问,其中一条边来自u to v 代表你对v有引用,root是线程工作栈中的东西,或者原生资源,没用的,有资格被java的GC收集。
现在的问题是 当我点击按钮并尝试创建一个Integer数组时,我上次创建的Integer数组肯定有资格被java的GC收集。那么为什么它会导致错误。
为这么长的描述道歉……我在提出问题时没有太多技巧,所以只是想把它说清楚。
另外,我用来启动jvm的参数是“java –Xmx256m”
【问题讨论】:
-
1+,感谢您在调试、创建 sscce 以及为看起来是您的问题所做的努力。我没有时间运行或调试您的程序,但我想知道您是否在持久化由侦听器带来的软引用方面遇到问题。
-
标签: java swing memory-leaks garbage-collection