2011-12-02 56 views
23

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

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

我仍然认为增加的内存:

Image description here

所以我的问题是:为什么仍锯齿模式?为什么当GC运行时不能保存所有的内存(每次gc运行(谷))时使用的内存增加10-20Kb(与之前的谷相比))?

编辑:

Java版本 “1.6.0_29”

的Java(TM)SE运行时环境(建立1.6.0_29-B11)

的HotSpot的Java(TM)客户端虚拟机(构建20.4-B02,混合模式,共享)

OS:Windows 7企业-32位

+0

我没有看到增加。记忆力上升,然后收集下来。它看起来像使用的最大内存随着时间的推移是不变的。 –

+0

另一个尝试在应用程序中查找内存泄漏的工具是[Plumbr](http://plumbr.eu)。它应该比摔跤探测器更容易,并试图从所有这些信息中推断出某些东西。 – Nikem

回答

10

为什么仍然有锯齿形图案?

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

为什么当GC运行它不会保存所有的内存(每次gc运行(谷))使用的内存增加10-20Kb(与前一个谷相比))?

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

+0

那么,我将如何获得关于引擎盖下正在发生的事情的更准确图片? – GoldfishGrenade

+0

在真正的程序中,还是在你的无操作回路测试程序中?在真正的程序中,堆转储将帮助您找出哪些对象无法被垃圾收集,这可以帮助您确定程序的哪些部分可能会被指责。 – ruakh

+0

+1这绝对是由于管理bean和任何用来与它们对话的协议(可能是RMI,因为它是默认的)所导致的。 – Fredrik

4

这是探查器的工件,没有探查器就没有分配。不同的配置文件会产生不同的工件,具体取决于它们如何记录数据。下面你看到的JProfiler的外观轮廓Nothing像:

enter image description here

少很多锯齿状花纹。然而,也有极小的内存消耗:

enter image description here

这是由于配置代理轮询java.lang.management.MemoryUsage JMX豆。最终,这种消耗也会触发垃圾收集。