Java 跟踪int[]的分配

Java 跟踪int[]的分配,java,debugging,Java,Debugging,在JVisualVM over JMX中查看我的远程应用程序时,我看到了空闲时内存使用的锯齿状变化: 获取堆转储并使用JVisualVM进行分析,我发现大量内存位于几个没有引用的大型int[]数组中,通过比较堆转储,我可以看到似乎是这些堆转储占用了内存并被GC周期性地回收 我很想找到这些,因为我自己的代码从来没有在知情的情况下分配任何int[]数组引起了我的兴趣 我确实使用了很多LIB,比如netty,所以罪魁祸首可能在别处。我确实有其他服务器,它们的框架组合大致相同,但没有看到这种锯齿状结构

在JVisualVM over JMX中查看我的远程应用程序时,我看到了空闲时内存使用的锯齿状变化:

获取堆转储并使用JVisualVM进行分析,我发现大量内存位于几个没有引用的大型
int[]
数组中,通过比较堆转储,我可以看到似乎是这些堆转储占用了内存并被GC周期性地回收

我很想找到这些,因为我自己的代码从来没有在知情的情况下分配任何
int[]
数组引起了我的兴趣

我确实使用了很多LIB,比如netty,所以罪魁祸首可能在别处。我确实有其他服务器,它们的框架组合大致相同,但没有看到这种锯齿状结构


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

做一个heapdump,找出哪些对象在存放它们。一旦你知道哪些对象持有数组,你应该很容易就知道是什么在分配它们

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

你为什么在乎

您已经告诉jvm垃圾收集器(GC)它最多可以使用1GB内存。Java使用的内存不足2.5亿

GC试图在垃圾收集的时间以及垃圾收集的工作强度方面保持明智。在图形中,不需要内存。jvm没有接近您设置的1GB限制。我看不出GC有任何理由应该非常努力。我也不知道你为什么会在乎

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

您是否尝试过通过JVisualVM“执行GC”按钮触发GC?该按钮应触发“停止世界”垃圾收集操作。当图表在这些锯齿形斜坡的中间时尝试一下——我预测使用将下降到锯齿或下面的底部。如果是这样的话,这就证明了内存锯齿只是垃圾累积,而GC做的是正确的

下面是我使用的java swing应用程序的内存使用情况屏幕截图:

注意锯齿图案

你说你担心int[]。当我启动内存分析器并让它分析所有我能看到的int[]的分配时

基本上,所有分配都来自ObjectOutputStream$HandleTable.growtEntries方法。看起来进行分配的线程是为处理网络消息而旋转的。

我怀疑这是由jmx本身造成的。可能由rmi(您是否使用rmi?)。或者调试器(是否连接了调试器?。

我只是想补充一点,锯齿模式非常正常,与
int[]
数组无关。发生这种情况是因为新的分配发生在Eden gen中,而短暂的集合只有在填满后才会触发,留下旧的gen。因此,只要您的程序执行任何分配,Eden gen就会填满,然后重复清空。特别是,当您在每单位时间内有固定数量的分配时,您将看到非常规则的锯齿模式

网上有很多文章详细介绍了Hotspot的GC是如何工作的,所以我不需要在这里详述。如果您根本不知道短命收集是如何工作的,那么您可能想查看一下(请参阅“世代GC”部分;“世代”和“短命”在本文中是同义词)


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

考虑到,即使你没有字面上有<代码>新INT[] /CUD>,您可能仍在自己分配这些。从理论上讲,数组是Java中唯一可以分配的大东西。@MarkoTopolnik是的,作为一个网络服务器,我确实有一些
byte[]
可以解释。我很好奇这些大的临时
int[]
,尽管我知道一旦有GC,它们就会被回收;它们可能会比我希望的更频繁地导致GCs,但它们似乎不会影响服务器。我只是好奇你会如何调试它。应该有帮助。@MarkoTopolnik thx。遗憾的是,当JVM处于远程状态时,内存分析器不可用,但这是一个非常好的线索。在本地运行服务器时,我看不到锯齿形,但是它的许多连接必须被模拟,所以它不是1:1的环境。羞耻;谢谢你的挖掘!我不知道是否只是这样,但通过JMX重复的远程轮询本身会产生垃圾(我们通过进程内和进程外的方式测量内存使用情况来观察到这一点)。这意味着您可以在实际程序不产生任何垃圾(或不是很多垃圾)的情况下查看它。谢谢您深思熟虑的回答,Ryan。当我说他们没有推荐人时,我的意思是我看不出谁持有他们——没有人持有。它们是垃圾。我还没有抓拍到它们,因为它们仍然被人持有。所以问题是,谁在创造它们,为什么?你会如何找到它?关于更大的问题,我正在对我的应用程序进行堆分析,因为在负载下,它使用的内存远远超过我喜欢的内存,我还面临来自该领域用户的各种内存不足报告。所以在空闲时看到这个锯齿是很有趣的追踪。而且,你的堆栈轨迹非常有趣,而且它很整洁