当前位置: 首页 > 知识库问答 >
问题:

对话框中的java垃圾收集

羊舌兴文
2023-03-14

*当我试图在JFrame中创建一个按钮时,我遇到了一个非常奇怪的java GC问题,当我单击该按钮时,它显示了一个需要处理和显示一些图像的JDialog,需要近200M内存。但问题是,当我关闭对话框并重新打开它时,有时会导致java.lang.OutofMemoryError。(不是每次)

为了解决这个问题,我简化了这个问题,做了一些实验,这使我更加困惑。

我在“实验”中使用的代码如下所示。当我单击帧中的按钮时,我为一个整数数组分配了160M内存,并显示了一个对话框,但是如果我关闭对话框并重新打开它,就会出现OutOfMemoryError。I调整代码,结果是:

>

  • 如果我不创建对话框并显示它,则没有内存问题。
  • 如果向对话框中添加一个调用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 Graph”从gc根访问,在“gc Graph”中,从u到v的边表示u有对v的引用,根是a线程工作堆栈中的东西,或者本地资源,它没有用,也没有资格被java的gc收集。

    现在的问题是,当我单击按钮并试图创建一个整数数组时,我上次创建的整数数组肯定有资格被Java的GC收集。所以为什么它会导致错误。

    为这么长的描述道歉…我在问问题时没有太多的策略,所以只是想把它说清楚。

    此外,我用来启动jvm的参数是“java-xmx256m”

  • 共有1个答案

    李鸿
    2023-03-14

    您在之前分配new int[40000000],而tmp仍然保留对最后一个int[40000000]的引用。
    tmp=new int[40000]这样的表达式中的操作顺序是:

    1. 新int[40000]
    2. 将对数组的引用分配给tmp

    所以在1中。tmp仍然保留对其最后一个值的引用。

    tmp = null;
    tmp = new int[40000000];
    
     类似资料:
    • 有人能给我解释一下原因吗?

    • 我知道对象存储在堆内存中。每个应用程序都有自己的堆内存,这是真的吗? 调用是否会降低应用程序的性能并降低应用程序的速度?或者,每当JVM完成垃圾收集时,它会降低应用程序的性能,并会使应用程序工作缓慢? 在哪些情况下进行部分垃圾回收,何时进行主要垃圾回收?

    • 每个java开发人员都知道,java对象不再使用时将被垃圾收集。我想知道JVM如何识别必须为垃圾收集选择的对象。(例如,如果我有10个对象。如果对10个对象中的2个进行垃圾收集,jvm将如何找到这两个对象)。 JVM使用标记和扫描算法(如果我是对的)。 1)例如我在下面提供字符串对象场景 //现在s1

    • 本文向大家介绍Java垃圾收集,包括了Java垃圾收集的使用技巧和注意事项,需要的朋友参考一下 示例 C ++方法-新增和删除 在像C ++这样的语言中,应用程序负责管理动态分配的内存所使用的内存。当使用new运算符在C ++堆中创建对象时,需要相应地使用delete运算符来处置该对象: 如果程序忘记了delete一个对象而只是“忘记”了该对象,则关联的内存将丢失给应用程序。这种情况的术语是内存泄

    • [GC(分配失败)[defnew:10931K->472K(12288K),0.0053905秒]10931K->10712K(39616K),0.0054285秒][times:user=0.00 sys=0.00,real=0.01秒] [GC(分配失败)[defnew:10712k->472k(12288k),0.0057686秒]20952k->20952k(39616k),0.00580

    • 主要内容:1 什么是Java 垃圾回收,2 Java 垃圾回收的优势,3 如何取消对象引用,4 finalize()方法,5 gc()方法,6 Java 垃圾回收的例子1 什么是Java 垃圾回收 在Java中,垃圾意味着未引用的对象。 垃圾回收是自动回收运行时未使用的内存的过程。换句话说,这是销毁未使用对象的一种方法。 我们在C语言中使用free() 函数,在C ++中使用delete()。但是,在Java中它是自动执行的。因此,java提供了更好的内存管理。 2 Java 垃圾回收的优势 它