追踪int []的分配
当通过JMX查看JVisualVM中的远程应用程序时,在空闲时看到了内存使用的锯齿:
拿堆转储和使用JVisualVM分析它,我看到一大块内存在一些没有引用的大型int[]
数组中,并且通过比较堆转储,我可以看到它似乎是这些内存和由GC定期回收。
我很好奇跟踪这些,因为它激起我的兴趣,我自己的代码永远不会故意分配任何int[]
数组。
我确实使用了很多像netty这样的库,所以罪魁祸首可能在别处。 我确实有其他服务器具有相同的框架组合,但没有看到这种锯齿。
我怎样才能发现谁在分配他们?
拿一个heapdump,找出有什么东西拿着它们。 一旦你知道什么对象持有阵列,你应该有一个简单的时间想法搞清楚什么是分配他们。
它不回答你的问题,但我的问题是:
你为什么在乎?
你已经告诉jvm垃圾收集器(GC)它可以使用高达1GB的内存。 Java使用少于250M。
GC试图对垃圾收集的时间和垃圾收集工作的难度做出明智的决定。 在你的图表中,没有内存需求。 jvm没有接近您设置的1GB限制。 我认为GC根本没有理由非常努力。 不知道你为什么会在乎。
垃圾回收器很懒惰是一件好事。 GC工作的越少,可用于应用程序的资源就越多。
您是否尝试通过JVisualVM“执行GC”按钮触发GC? 该按钮应该触发“停止世界”垃圾收集操作。 当图表位于其中一个锯齿形锯齿的中间时尝试 - 我预测使用量会下降到锯齿底部或以下。 如果确实如此,那证明记忆锯齿只是垃圾堆积而GC正在做正确的事情。
以下是我使用的java swing应用程序的内存使用情况截图:
注意锯齿图案。
你说你担心int []。 当我启动内存分析器并对其进行配置时,我可以看到int []的分配
基本上所有分配都来自ObjectOutputStream $ HandleTable.growEntries方法。 它看起来像分配的线程被分解成处理网络消息。
我怀疑它是由jmx本身造成的。 可能由rmi(你使用rmi?)。 或调试器(你有调试器连接?)。
我只是想我会加入这个问题,锯齿模式是非常正常的,没有必要与你的int[]
数组。 它的发生是因为新的分配发生在伊甸园,而一个短暂的集合只有在它已经完成时才会被触发,留下旧有的。 所以只要你的程序做了任何分配,Eden gen就会填满然后反复空出。 特别是,当你每单位时间有一定量的分配时,你会看到非常规则的锯齿图案。
网上有很多文章详细描述了Hotspot的GC如何工作,所以我不需要在这里扩展。 如果你完全不知道短暂的收集是如何工作的,你可能想看看维基百科关于这个问题的文章(参见“Generational GC”部分;“generational”和“ephemeral”在这种情况下是同义词)。
至于int[]
数组,但是,它们有点神秘。 我也看到了这些,关于这个问题,还有另外一个问题没有给出真正的答案。 没有引用的对象在堆转储中显示并不是很正常,因为堆转储通常只包含活动对象(因为在实际转储堆之前,热点始终执行停止世界集合)。 我个人的猜测是,它们是作为某种内部JVM数据结构的一部分进行分配的(因此只能从Hotspot的C ++部分引用,而不是从Java堆引用),但这实际上只是一种纯粹的猜测。
上一篇: track down allocations of int[]
下一篇: Replacing a fragment with another fragment of the same class