代码之家  ›  专栏  ›  技术社区  ›  Tiina

Java堆内存管理内存不足

  •  2
  • Tiina  · 技术社区  · 6 年前

    当Netty异步服务器和客户端项目在Linux上运行时,它会耗尽所有可用内存,如下所示: linux console

    所以我在windows上运行它,jmc显示heap如下:

    JMC memory

    我的问题是:为什么windows和linux的行为不同,有没有什么地方可以配置linux jvm来释放堆内存?为什么windows(gc)中会有堆释放呢?如何找出占用大量内存的可疑代码?

    编辑 :Linux是4G,Windows是8G,但我不认为绝对值会导致运行结果的差异。project不直接处理原始的bytebuff,它使用 HttpServerCodec HttpObjectAggregator 为了比特布夫。在Linux中运行的命令是 java -jar xx.jar 是的。我不仅想知道 为什么不同,为什么锯齿 而且 如何找到占用这么多内存的 是的。jmc显示了另一个图,我不知道为什么线程可以有这么高的块号。网络线程IO有99行71ms。 JMC threads

    更新时间: 现在我想 找出代码的哪个部分占用了这么多内存 .jmc堆显示eden空间非常高,我对它进行了搜索,发现eden空间用于 new 反对。最初,项目使用的是spring boot,它使用tomcat servlet 3.0作为容器,使用apache httpclient池作为客户端,现在只有这些部分通过netty异步服务器和netty异步客户端进行了更改,而其他部分则保留下来(仍然使用spring进行bean管理)。netty服务器和客户机处理程序对所有请求都是共享的(处理程序是singleton spring bean)。这么小的变化,我不相信 新的 对象显著增加,以1.35g内存结束 JMC heap

    更新 在分别运行netty和springboot项目之后,我得到了更多的统计数据:

    1. 操作系统内存8g.springboot版本项目:PS旧版本:容量=195MB;已使用=47MB;已使用24%。它有692971个对象,总大小为41848384。
    2. 操作系统内存16G。Netty版本项目:PS旧版本:容量=488MB;已使用327MB;已使用67%。它有1243432个对象,总大小为221427824。

    netty版本:堆转储显示它有279255个类实例 io.netty.buffer.PoolSubpage 与第二大7222个类实例相比 org.springframework.core.MethodClassKey .两个版本都有服务(我们自己的类)对象限制,不超过3000个。

    我试着和 -Xmx1024m 在4g内存linux上,仍然会导致同样的内存不足问题。

    1 回复  |  直到 6 年前
        1
  •  3
  •   Stephen C    6 年前

    您在windows上看到的行为是正常的gc行为。应用程序正在生成垃圾,然后达到导致GC运行的阈值。gc释放了大量堆。然后应用程序再次启动。结果是堆占用中出现锯齿状。

    这很正常。每个jvm的行为或多或少都是这样的。


    Linux上的行为看起来像是有人试图在本机内存中分配大容量(77MB)的内存,但失败了,因为操作系统拒绝为JVM提供那么多内存。通常情况下,这是因为操作系统耗尽了资源;例如物理RAM、交换空间等。

    Windows 8g、Linux 4G。

    这可能就是原因。Linux系统只有Windows系统的一半物理内存。如果您运行的netty有一个很大的java堆,并且您的linux操作系统没有配置任何交换空间,那么jvm可能正在使用所有可用的虚拟内存。它甚至可能发生在jvm启动时。

    (如果我们假设windows和linux的最大堆大小设置相同,那么在windows上至少有4.5gb的虚拟地址空间可用于其他用途。在Linux上,只有0.5GB。0.5gb必须保持所有非堆jvm利用率…加上操作系统和其他各种用户空间进程。很容易看出你怎么能利用所有这些…导致分配失败。)

    如果我的理论是正确的,那么解决方案就是更改jvm命令行选项,使-xmx更小。

    (或增加可用的物理/虚拟内存。但是要注意通过添加交换空间来增加虚拟内存。如果虚拟/物理比率太大,则可能会导致虚拟内存“抖动”,从而导致糟糕的性能。)