在对话框中收集java垃圾 [英] java garbage collecting in dialog
问题描述
为了解决这个问题,我简化了这个问题并做了一些实验,这让我更加困惑。
我在实验中使用的代码如下所示。
当我单击框架中的一个按钮时,我为整数数组分配了160M内存,并显示一个对话框但是,如果关闭对话框并重新打开该对话框,将出现OutOfMemoryError 。代码和结果是:
- 如果我不创建对话框并显示它,则不会出现内存问题。
- 如果我添加了一个调用System.gc()到对话框的windowsCloseListener,没有内存问题。
-
如果我在运行时调用System.gc ()方法,显示内存问题。
public class TestController {
int [] tmp;
class TDialog扩展了JDialog {
public TDialog(){
super();
this.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
//如果我取消这段代码,OutOfMemoryError似乎在这种情况下消失
//但我确定它不是一个可接受的解决方案
/ *
this.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e){
System.out.println(windowsclose);
TDialog.this.dispose();
System.gc ();
}
});
* /
}
}
TDialog dia;
$ b $ public void run(){
//如果我在这里执行System.gc(),OutOfMemoryError仍然存在
// System.gc();
tmp = new int [40000000];
for(int i = 0; itmp [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);
}
});
code $
我已经阅读了很多描述java的GC工作原理的文章。我认为如果java试图在堆中分配一些空间并且它没有足够的可用空间,那么java将会执行gc,并且如果一个对象不能通过GC graph从GC根访问,其中一个边u到v表示你有一个对v的引用,root是一个线程工作栈或本地资源中的东西,它没有用,并且可以被java的GC收集。
现在问题出现了当我点击按钮并尝试创建一个Integer数组时,我上次创建的Integer数组肯定有资格被java的GC收集。那么为什么它会导致错误。 p>
另外,我用来启动jvm的参数是java -Xmx256m
解决方案您之前正在分配
新的int [40000000]
,而tmp
仍然保留对最后一个int [40000000]
。
表达式中的操作顺序如tmp = new int [40000]
是:
-
new int [40000]
- 将对数组的引用赋给
tmp
1
tmp
仍然保留对其最后一个值的引用。尝试做:tmp = null;
tmp = new int [40000000];
*I'm now encountering a very strange java GC problem when I trying to make a button in a JFrame, and when I click the button, it display a JDialog which need to deal with and show some images and need nearly 200M memory. But the problem is when I close the dialog and reopen it, sometimes it cause java.lang.OutOfMemoryError. (not every times)
Trying to solve the problem, I simplify this problem and make some experiment, which cause me more confused.
The Code I used in my " experiment " is showed below. When I click a button in a frame, I allocate 160M memory for an integer array, and display a dialog, But If I close the dialog and reopen it, OutOfMemoryError appears. I adjusting the code and the result is:
- 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); } }); } }
I’ve read about a lot articles which describe how java’s GC work. I think if java trying to allocate some space in the heap and it do not have enough free space, java will do gc, and if a object can’t be accessed from the gc root through "GC graph", in which a edge from u to v represent u have a reference to v, root is something in the a thread working stack, or native resources, It’s useless and qualified to be collected by java’s GC.
Now the problem is When I click the button and trying to create an Integer array, the Integer array I create last time is certainly qualified to be collected by java’s GC. So why it caused Error.
Apologize for Such A Long Description…I don’t have much tactics in asking problem, so just trying to make it clear.
Besides, The parameter I used to start jvm is " java –Xmx256m"
解决方案You're allocating
new int[40000000]
before whiletmp
still holds the reference to the lastint[40000000]
.
The order of operation in an expression liketmp = new int[40000]
is:new int[40000]
- Assign the reference to the array to
tmp
So in 1.
tmp
is still holding the reference to it's last value.Try doing:
tmp = null; tmp = new int[40000000];
这篇关于在对话框中收集java垃圾的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
-