【问题标题】:Why does an empty Java program consume memory?为什么一个空的 Java 程序会消耗内存?
【发布时间】:2012-01-11 19:28:28
【问题描述】:

我正在探索 Java 中的内存使用情况,以了解为什么我的程序会泄漏内存。在我的主 while 循环中剥离代码后,随着时间的推移,我的内存使用量仍然会增加。思考一个空程序的内存使用情况:

class Nothing
{    public static void main(String[] args)
     {    while(true);    }
}

我还是看到了内存的增加:

所以我的问题是:为什么还有锯齿图案?为什么 GC 运行时没有保存所有内存(每次 gc 运行(山谷)使用的内存增加 10-20Kb(与之前的山谷相比))?

编辑:

java 版本“1.6.0_29”

Java(TM) SE 运行时环境(内部版本 1.6.0_29-b11)

Java HotSpot(TM) 客户端虚拟机(build 20.4-b02,混合模式,共享)

操作系统:Windows 7 Enterprise-32 位

【问题讨论】:

  • 我没有看到增加。内存上升,然后收集下来。看起来使用的最大内存随着时间的推移是恒定的。
  • 另一个尝试在应用程序中查找内存泄漏的工具是Plumbr。它应该比与分析器搏斗并试图从所有这些信息中推断出一些东西要容易得多。

标签: java memory-leaks while-loop


【解决方案1】:

这是分析器的工件,没有分析器就没有分配。不同的分析器会产生不同的工件,具体取决于它们记录数据的方式。下面你会看到分析NothingJProfiler 的样子:

锯齿形图案要少得多。但是,内存消耗也很小:

这是因为分析代理轮询java.lang.management.MemoryUsage JMX bean。最终这种消费也会触发垃圾回收。

【讨论】:

    【解决方案2】:

    为什么还有锯齿纹?

    如果我没记错的话,部分原因是监视器本身强制应用程序创建临时对象,其中包含有关垃圾收集状态和内存使用情况的信息。

    为什么 GC 运行时没有保存所有内存(每次 gc 运行(山谷)使用的内存增加 10-20Kb(与之前的山谷相比))?

    我相信监视器在垃圾收集后不会立即看到已使用的内存量,而是必须经常轮询以查看内存使用情况。因此,感知到的“谷”必然比真正的谷要高一些。我猜测在山谷中感知到的内存使用量增加只是这种差异的随机产物,并且会随着时间的推移而被抵消。 (也就是说,我认为每个周期实际上不会发生 10-20 KB 的内存泄漏。)

    【讨论】:

    • 那么我该如何更准确地了解幕后发生的事情呢?
    • 在实际程序中,还是在您的无操作循环测试程序中?在实际程序中,堆转储将帮助您确定哪种对象未能被垃圾收集,这可以帮助您确定程序的哪一部分可能是罪魁祸首。
    • +1 这绝对是由管理 bean 和用于与它们通信的任何协议引起的(可能是 RMI,因为它是默认的)。
    • 那么通过任务管理器>资源监视器查看会更好吗?
    • 这不会给你太多信息。我认为您正在使用的工具可能会很有用;你只是不能指望它对你的程序有 zero 影响。如果您在实际存在内存泄漏的程序中寻找内存泄漏,相比之下,分析器自身的影响将微乎其微。通过从您的测试程序中删除 all 内存分配,您创建了一种情况,即探查器自身的效果是您看到的 only 事物——这与有用的相反.
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多