0

您好,我有一个使用 java.swing.timer 的应用程序,这是在循环中。问题是我的 Windows 内存进程仍然发光,并且不会停止。我试图清理我的变量,使用 System.gc() 等......但不工作。我制作了一个示例来使用线程、timerstack 和 swing timer 进行测试,我在 jcombobox 中添加了 itens 并且内存仍在增加。

代码如下:

//我的计时器

@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!");

}

请帮忙!=(

4

2 回答 2

2

目前尚不清楚您发布的一小段代码实际上是否存在问题。

无论哪种方式,你都无法控制你想控制的东西

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

来自以下文章感谢内存(了解 JVM 如何在 Windows 和 Linux 上使用本机内存)

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

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

javac并且 JIT 编译器像使用本机内存一样

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

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

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

我什至不会开始引用有关线程的部分,我认为您的想法是, -Xmx它无法控制您认为它控制的内容,它控制 JVM 堆,并非所有内容都进入 JVM 堆,并且堆占用更多您指定用于管理和簿记的本机内存。

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

你所关心的你无法控制,反正不是直接

您应该关注的是您可以控制的内容,这确保您不会保留比您需要的时间更长的引用,并且您不会不必要地重复事物。Java 中的垃圾收集例程经过高度优化,如果您了解它们的算法是如何工作的,就可以确保您的程序以最佳方式运行,以使这些算法能够正常工作。

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

在其他语言中被认为是内存泄漏的事情/根本原因与 Java 中的垃圾收集系统不同。

在 Java 中,内存很可能不会被一个正在泄漏的 uber-object 消耗(其他环境中的悬空引用)。

中间对象可能被垃圾收集器保留的时间比预期的要长,因为它们所处的范围以及在运行时可能会发生变化的许多其他事情。

示例:垃圾收集器可能会确定有候选者,但因为它认为还有大量内存可用,所以在那个时间点将它们刷新出来可能过于昂贵,它会等到内存压力越来越大。

垃圾收集器现在真的很好,但它不是魔法,如果你在做退化的事情,它会导致它不能以最佳方式工作。互联网上有很多关于所有 JVM 版本的垃圾收集器设置的文档。

这些未引用的对象可能只是没有达到垃圾收集器认为需要它们才能从内存中清除它们的时间,或者可能存在对它们的引用由其他对象(List)持有,例如你不实现仍然指向该对象。这就是 Java 中最常见的泄漏,更具体地讲是引用泄漏。

示例:如果您知道需要String使用StringBuilder创建它而new StringBuilder(4096);不是默认值(例如 32)来构建 4K,并且将立即开始创建垃圾,这些垃圾可以代表您认为对象大小的许多倍。

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

我没有看到任何提及OutOfMemoryError

您的代码可能没有问题,垃圾收集系统可能没有承受足够的压力来启动和释放您认为应该清理的对象。您认为的问题可能不是,除非您的程序因OutOfMemoryError. 这不是 C、C++、Objective-C 或任何其他手动内存管理语言/运行时。您无法以您期望的详细程度来决定内存中的内容。

于 2012-09-06T18:43:12.043 回答
-1

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

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

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

于 2012-09-06T18:34:27.027 回答