当netty异步服务器和客户端项目在linux上运行时,它会耗尽所有可用内存,如下所示:
所以我在windows上运行它,JMC像这样显示堆:
我的问题是:为什么windows和linux的行为不同,有什么地方可以配置linux来释放堆内存吗?以及为什么windows中有堆释放(GC)?如何找出占用这么多内存的可疑代码?
编辑:linux是4G,windows是8G,但我不认为绝对值会导致运行结果的差异。项目不直接处理原始字节码,它对bytebuf使用HttpServerCodec
和HttpObjectAggregator
。在linux中运行的命令是java -jar xx.jar
。我不仅想知道为什么不同,为什么锯齿,还有如何定位占用这么多内存的。JMC显示了另一个数字,我不知道为什么线程会有这么高的块号。netty线程IO有一个99LINE71ms。
更新:,现在我想定位代码的哪一部分占用了这么多的内存。JMC堆显示伊甸园空间很高,我发现它是new
对象的伊甸园空间。最初,该项目使用了spring-boot,其中包含tomcat servlet 3.0作为容器,使用apache httpclient池作为客户端,现在只有这些部分通过使用netty异步服务器和netty异步客户端进行了更改,而其他部分仍然保留(仍然使用spring进行bean管理)。所有请求都共享Netty服务器和客户端处理程序(处理程序是单例spring )。通过这么小的更改,我不相信new
对象的数量会显着增加,最终会以1.35G内存结束
在分别运行netty和springboot项目之后更新了,我获得了更多的统计数据:
netty版本:堆转储显示它有279 255个类io.netty.buffer.PoolSubpage
实例,而类org.springframework.core.MethodClassKey
的第二大实例是7222个。这两个版本都有服务(我们自己的类)对象限制,不超过3000。
我曾尝试在4G内存linux上运行-Xmx1024m
,但仍然造成内存不足问题。
发布于 2018-07-03 07:35:19
在Windows上看到的行为是正常的GC行为。应用程序正在生成垃圾,然后到达导致GC运行的阈值。GC释放了很多堆。然后应用程序重新启动。结果是在堆占用率中出现锯齿模式。
这很正常。每个JVM的行为或多或少都是这样的。
Linux上的行为似乎是试图在本机内存中分配一些大的东西(77 on ),而失败是因为操作系统拒绝给JVM足够多的内存。通常情况下,这是因为操作系统耗尽了资源;例如物理RAM、交换空间等等。
Windows 8G,linux 4G。
这可能就解释了。Linux系统的物理内存只有Windows系统的一半。如果您正在使用大型Java堆运行netty,并且您的Linux操作系统没有配置任何交换空间,那么JVM使用的是所有可用的虚拟内存。它甚至可能发生在JVM启动时。
(如果我们假设Windows和Linux的最大堆大小相同,那么在Windows上至少有4.5GB的虚拟地址空间可用于其他事情。在Linux上,只有0.5GB。而0.5GB必须保存所有的非堆JVM利用率.加上操作系统和其他各种用户空间进程。很容易看出你是怎么利用这些的.导致分配失败。)
如果我的理论是正确的,那么解决方案将是更改JVM命令行选项,使-Xmx变小。
(或增加可用物理/虚拟内存。但是要注意通过添加交换空间来增加虚拟内存。如果虚拟/物理比率太大,你可以得到虚拟内存“猛击”,这会导致糟糕的性能。)
https://stackoverflow.com/questions/51148274
复制相似问题