4

我有一个非常简单的类,它有一个整数变量。我只是将变量“i”的值打印到屏幕上并增加它,并使线程休眠 1 秒。当我针对此方法运行分析器时,即使我没有创建任何新变量,内存使用量也会缓慢增加。执行此代码大约 16 小时后,我看到内存使用量增加到 4 MB(启动程序时最初为 1 MB)。我是Java新手。任何人都可以帮助解释我哪里出错了,或者为什么即使没有创建新变量,内存使用量也会逐渐增加?提前致谢。

我正在使用 netbeans 7.1 及其分析器来查看内存使用情况。

    public static void main(String[] args)
    {
        try
        {
            int i = 1;
            while(true)
            {
                System.out.println(i);
                i++;
                Thread.sleep(1000);
            }
        }
        catch(InterruptedException ex)
        {
            System.out.print(ex.toString());
        }
    }

程序启动时的初始内存使用量:1569852 字节。

执行循环 16 小时后的内存使用量:4095829 字节

我在这篇文章中的代码遇到的问题的屏幕截图

4

7 回答 7

2

它不一定是内存泄漏。System.out.println(i);当 GC 运行时,将收集语句中分配的对象(我假设) 。Java 中的内存泄漏是指内存被 GC无法回收的无用对象填满。

println(i)用于将Integer.toString(int)转换int为字符串,并且String每次都分配一个新的。这不是泄漏,因为一旦将字符串复制到输出缓冲区,字符串将变得无法访问并成为 GC 的候选对象。

其他可能的内存分配来源:

  • Thread.sleep 可以在幕后分配对象。

  • 某些私有 JVM 线程可能会导致此问题。

  • 分析器用来监视 JVM 状态的“java 代理”代码可能会导致这种情况。它必须组装数据并将数据通过套接字发送到分析器应用程序,这很可能涉及分配 Java 对象。它也可能在 JVM 的堆或非堆内存中积累东西。

但只要在 GC 运行时 / 可以回收空间,这并不重要。如果不能,那么您可能在您正在使用的分析器中发现了 JVM 错误或错误。(尝试用一个很长的睡眠来替换循环,看看“泄漏”是否仍然存在。)这是否是由分析引起的缓慢泄漏可能无关紧要......因为您通常不运行生产代码启用了这么长时间的分析。


注意:System.gc()不保证调用会导致 GC 运行。阅读 javadoc。

于 2012-06-08T10:55:17.747 回答
1

我在这段代码中没有看到任何内存泄漏。您应该了解 Java 中的垃圾收集器是如何工作的以及它的策略。基本上说 GC 在需要之前不会清理 - 如特定策略所示。

您也可以尝试调用System.gc()

这些对象可能是在两个 Java Core 函数中创建的。

于 2012-06-08T10:56:25.017 回答
0

这是由于控制台中显示的文本以及整数的大小(一点点)。

Java 打印函数使用 8 位 ASCII,因此 56000 次打印一个数字,每个字符 8 个字节很快就会占用内存。

于 2012-06-08T10:55:43.940 回答
0

按照本教程查找内存泄漏:使用 VisualVM 分析 Java 应用程序中的内存泄漏。您必须在开始时制作应用程序的快照,并在一段时间后制作另一个快照。使用 VisualVM,您可以执行此操作并将这些与快照进行比较。

于 2012-06-08T10:56:37.763 回答
0

尝试将 JVM 内存上限设置得如此之低,以致可能的泄漏会导致它耗尽内存。

如果使用的内存达到该限制并继续愉快地工作,那么垃圾收集就可以完成它的工作。

如果相反,它会爆炸,那么你就有一个真正的问题......

于 2012-06-08T11:38:12.000 回答
0

正如分析器的图表所显示的那样,这似乎不是泄漏。图表在特定时间间隔后急剧下降,即执行 GC 时。如果图表继续稳步攀升,那将是一个泄漏。之后剩余的堆空间必须由 thread.sleep() 使用,并且(如上面的答案之一所述)来自探查器的某些代码。

您可以尝试在其中运行 VisualVM%JAVA_HOME%/bin并分析您的应用程序。它还为您提供了随意执行 GC 的选项以及更多选项。

我注意到我使用的 VisualVM 的更多功能正在消耗更多内存(高达 10MB)。所以这个增加,它也必须来自你的分析器,但它仍然不是泄漏,因为空间是在 GC 上回收的。

于 2012-06-15T10:10:23.473 回答
-1

没有printlns会发生这种情况吗?换句话说,也许让 printlns 显示在控制台上是消耗内存的原因。

于 2012-06-08T10:53:01.900 回答