WIndows Memory raise

时间:2012-09-06 18:26:33

标签: java

您好我有一个使用java.swing.timer的应用程序,这是在循环中。问题是我的Windows内存进程仍然发光,并且不要停止。我试图清理我的变量,使用System.gc()等......并且不工作。我用一个样本来测试这个用线程,timerstack和swing计时器,我把它添加到一个jcombobox中,内存仍然在升高。

代码如下:

//我的计时器

@Action
public void botao_click1() {
    jLabel1.setText("START");
    timer1 = new java.util.Timer();
    timer1.schedule(new TimerTask() {

        @Override
        public void run() {
            adicionarItens();
            limpar();
        }
    }, 100, 100);
}

@Action
public void botao_click2() {
    thread = new Thread(new Runnable() {

        public void run() {
            while (true) {
                adicionarItens();
                try {
                    Thread.sleep(100);
                    limpar();
                } catch (InterruptedException ex) {
                    Logger.getLogger(MemoriaTesteView.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        }
    });
    thread.start();
}

private void limpar() { // CleanUp array and jcombobox

    texto = null;

    jComboBox1.removeAllItems();
    jComboBox1.setVisible(false);
    //jComboBox1 = null;

    System.gc();

}

private void adicionarItens() { //AddItens

    texto = new String[6];

    texto[0] = "HA";
    texto[1] = "HA";
    texto[2] = "HA";
    texto[3] = "HA";
    texto[4] = "HA";
    texto[5] = "HA";

    //jComboBox1 = new javax.swing.JComboBox();

    jComboBox1.setVisible(true);

    for (int i = 0; i < texto.length; i++) {
        jComboBox1.addItem(texto[i].toString());
    }

    System.out.println("System Memory: "
            + Runtime.getRuntime().freeMemory() + " bytes free!");

}

请帮助! =(

2 个答案:

答案 0 :(得分:2)

您发布的一小段代码确实存在问题。

无论哪种方式,您都无法控制您想要控制的内容

-Xmx仅控制Java堆,它不会控制JVM对本机内存的消耗,根据实现情况完全不同地消耗它。

来自以下文章Thanks for the Memory ( Understanding How the JVM uses Native Memory on Windows and Linux )

维护堆和垃圾收集器使用您无法控制的本机内存。

  

需要更多的本机内存来维护状态   内存管理系统维护Java堆。数据结构   必须分配以跟踪免费存储并记录进度   收集垃圾。这些数据结构的确切大小和性质   随实施而变化,但许多与大小成正比   堆。

并且JIT编译器使用本机内存,就像javac

一样
  

字节码编译使用本机内存(与静态内存相同)   编译器如gcc需要内存运行),但两者都是输入(   字节码)和JIT的输出(可执行代码)也必须   存储在本机内存中。包含许多的Java应用程序   JIT编译的方法比较小的应用程序使用更多的本机内存。

然后你有使用本机内存的类加载器

  

Java应用程序由定义对象结构的类组成   和方法逻辑。它们还使用Java运行时类中的类   库(如java.lang.String)并可能使用第三方   库。只要这些类需要存储在内存中   他们正在被使用。如何存储类因实现而异。

我甚至没有开始引用关于Threads的部分,我想你明白了 -Xmx不控制您认为它控制的内容,它控制JVM堆,而不是所有内容 进入JVM堆,并且堆占用了您指定的更多本机内存 管理和簿记。

我在任何地方都没有看到OutOfMemoryExceptions

你关注的是你无法控制,而不是直接控制

您应该关注的是控制中的内容,即确保您不会持续超过您需要的参考,并且您不会不必要地复制内容。 Java中的垃圾收集例程已经过高度优化,如果您了解其算法的工作原理,您可以确保您的程序以最佳方式运行,以使这些算法正常工作。

Java堆内存不像其他语言的手动管理内存,这些规则不适用

在其他语言中被认为是内存泄漏与Java及其垃圾收集系统不同,它们的原因和根本原因不同。

Java内存中很可能不会被泄漏的单个超级对象(在其他环境中悬挂引用)消耗掉。

由于垃圾收集器所处的范围以及许多其他可能在运行时发生变化的事情,中间对象可能会被垃圾收集器保持的时间超过预期。

示例:垃圾收集器可能会认为有候选者,但是因为它认为仍有大量内存可能需要花费太多时间才能将其清除掉时间点,它会等到记忆压力升高。

垃圾收集器现在真的很好,但它并不神奇,如果你正在做退化的事情,它将导致它不能最佳地工作。互联网上有很多关于所有JVM版本的垃圾收集器设置的文档。

这些未引用的对象可能还没有达到垃圾回收器认为需要它们从内存中清除它们的时间,或者可能有一些其他对象(List对它们进行引用。例如,你没有意识到仍然指向该对象。这就是Java中最常被称为 leak 的东西,它更具体地是一个参考泄漏。

示例:如果您知道需要使用String构建4K StringBuilder,请使用new StringBuilder(4096);创建char[],而不是默认值,即32和将立即开始创建垃圾,可以表示您认为该对象应该是大小明智的很多次。

您可以发现使用VisualVM实例化了多少类型的对象,这将告诉您需要了解的内容。没有一个闪烁的大灯指向单个类的单个实例,它说,&#34;这是大内存消费者!&#34;,除非只有一个实例你正在读一些大量文件的char[],这也是不可能的,因为许多其他类在内部使用OutOfMemoryError;然后你几乎已经知道了。

我没有看到提及OutOfMemoryError

您的代码中可能没有问题,垃圾收集系统可能没有受到足够的压力来启动和解除分配您认为应该清理的对象起来。 您认为是一个问题可能并非如此,除非您的程序与{{1}}崩溃。这不是C,C ++,Objective-C或任何其他手动内存管理语言/运行时。你不能在你期望的细节层面上决定你的内存是什么。

答案 1 :(得分:-1)

从理论上讲,Java不受基于C语言可能具有的“泄漏”的影响。但是,设计一个以或多或少无限制的方式增长的数据结构仍然很容易,无论你是否打算这样做。

当然,如果您安排基于计时器的任务等,它们将一直存在,直到时间到期并且任务已完成(或取消),即使您没有保留对它们的引用。 / p>

此外,一些Java环境(Android因此而臭名昭着)以不受普通GC操作影响的方式分配图像等,并且可能导致堆以无限制的方式增长。