追踪int 的分配

通过JMX在JVisualVM中查看我的远程应用程序时,我发现在空闲时看到了内存使用情况:

在此处输入图像描述

使用堆转储并使用JVisualVM对其进行分析,我看到一大块内存位于几个没有引用的大型int[]数组中,通过比较堆转储,我可以看到它们似乎正在占用内存和由GC定期收回。

我很想跟踪这些,因为它引起了我的兴趣,我自己的代码永远不会故意分配任何int[]数组。

我确实使用了很多像netty这样的库,所以罪魁祸首可能在其他地方。 我确实有其他服务器具有相同的框架组合,但在那里看不到这个锯齿。

我怎样才能发现谁在分配它们?

获取一个堆转储并找出哪些对象持有它们。 一旦你知道什么对象持有arrays,你应该有一个简单的时间想法找出分配它们的内容。

它没有回答你的问题,但我的问题是:

你为什么在乎?

你已经告诉jvm垃圾收集器(GC)它可以使用高达1GB的内存。 Java的使用量不到250M。

GC尝试了解垃圾收集的时间以及它在垃圾收集中的工作方式。 在图表中,没有内存需求。 jvm并不接近你设置的1GB限制。 我认为GC没有理由应该非常努力。 不确定为什么你会关心。

垃圾收集器懒惰是件好事。 GC工作越少,您的应用程序可用的资源就越多。

您是否尝试通过JVisualVM“执行GC”按钮触发GC? 该按钮应该触发“停止世界”垃圾收集操作。 当图形位于其中一个锯齿斜坡的中间时尝试它 – 我预测使用将下降到锯齿的底部或以下。 如果是这样,那certificate记忆锯齿只是垃圾堆积而GC正在做正确的事情。

以下是我使用的java swing应用程序的内存使用情况的屏幕截图: 在此处输入图像描述

注意锯齿形图案。

你说你担心int []。 当我启动内存分析器并让它描述一切时,我可以看到int []的分配

在此处输入图像描述

基本上所有分配都来自ObjectOutputStream $ HandleTable.growEntries方法。 它看起来像分配的线程被旋转以处理网络消息。
我怀疑它是由jmx本身引起的。 可能是rmi(你用rmi吗?)。 或调试器(您是否连接了调试器?)。

我只是想我会在这个问题中添加锯齿模式是非常正常的,并且与int[]数组没有任何关系。 之所以发生这种情况,是因为新的分配发生在Eden-gen中,而短暂的集合只有在填满之后才会被触发,留下旧的。 因此,只要您的程序完成任何分配,Eden gen就会填满然后反复清空。 特别是,当你每单位时间有一定数量的分配时,你会看到一个非常规则的锯齿模式。

网上有大量文章详细介绍了Hotspot GC的工作原理,因此我无需在此处进行扩展。 如果您根本不知道短暂收集的工作原理,您可能需要查看Wikipedia关于该主题的文章 (参见“Generational GC”部分;“generational”和“ephemeral”在此上下文中是同义词)。

然而,对于int[]数组,它们有点神秘。 我也看到了这些,并且在这里有关于它们的主题的另一个问题没有任何真正的答案。 堆转储中没有引用的对象实际上并不正常,因为堆转储通常只包含活动对象(因为Hotspot在实际转储堆之前总是执行stop-the-world集合)。 我个人的猜测是它们被分配为某种内部JVM数据结构的一部分(因此只有来自Hotspot的C ++部分而不是来自Java堆的引用),但这实际上只是一个纯粹的猜测。