更新到wildfly 18后直接缓冲内存OutOfMemoryError
Direct buffer memory OutOfMemoryError after updating to wildfly 18
将环境从 Wildfly 13
更新到 Wildfly 18.0.1
后,我们遇到了
A channel event listener threw an exception: java.lang.OutOfMemoryError: Direct buffer memory
at java.base/java.nio.Bits.reserveMemory(Bits.java:175)
at java.base/java.nio.DirectByteBuffer.<init>(DirectByteBuffer.java:118)
at java.base/java.nio.ByteBuffer.allocateDirect(ByteBuffer.java:317)
at org.jboss.xnio@3.7.3.Final//org.xnio.BufferAllocator.allocate(BufferAllocator.java:57)
at org.jboss.xnio@3.7.3.Final//org.xnio.BufferAllocator.allocate(BufferAllocator.java:55)
at org.jboss.xnio@3.7.3.Final//org.xnio.ByteBufferSlicePool.allocateSlices(ByteBufferSlicePool.java:162)
at org.jboss.xnio@3.7.3.Final//org.xnio.ByteBufferSlicePool.allocate(ByteBufferSlicePool.java:149)
at io.undertow.core@2.0.27.Final//io.undertow.server.XnioByteBufferPool.allocate(XnioByteBufferPool.java:53)
at io.undertow.core@2.0.27.Final//io.undertow.server.protocol.http.HttpReadListener.handleEventWithNoRunningRequest(HttpReadListener.java:147)
at io.undertow.core@2.0.27.Final//io.undertow.server.protocol.http.HttpReadListener.handleEvent(HttpReadListener.java:136)
at io.undertow.core@2.0.27.Final//io.undertow.server.protocol.http.HttpReadListener.handleEvent(HttpReadListener.java:59)
at org.jboss.xnio@3.7.3.Final//org.xnio.ChannelListeners.invokeChannelListener(ChannelListeners.java:92)
at org.jboss.xnio@3.7.3.Final//org.xnio.conduits.ReadReadyHandler$ChannelListenerHandler.readReady(ReadReadyHandler.java:66)
at org.jboss.xnio.nio@3.7.3.Final//org.xnio.nio.NioSocketConduit.handleReady(NioSocketConduit.java:89)
at org.jboss.xnio.nio@3.7.3.Final//org.xnio.nio.WorkerThread.run(WorkerThread.java:591)
应用程序方面没有任何更改。我查看了缓冲池,似乎有些资源没有被释放。我触发了几次手动 GC,但几乎没有任何反应。 (正常运行时间 2 小时)
在旧配置之前它看起来像这样(正常运行时间 >250h):
现在我做了很多研究,我能找到的最接近的东西是 post here on SO。然而,这是与 websockets 结合使用的,但是有 no websockets 在使用中。
我读了几篇(好)文章(1,2,3,,5,6) and watched this video 关于这个话题。
我尝试了以下操作但没有任何效果:
- OutOfMemoryError 发生在 5GB,因为堆是 5GB => 我将 MaxDirectMemorySize 减少到 512m,然后是 64m,但是 OOM 发生得更快
- 我设置
-Djdk.nio.maxCachedBufferSize=262144
- 我查看了IO worker的数量:96(6cpus*16),貌似比较合理。该系统通常具有短寿命线程(最大池大小为 13)。所以这不可能是我猜的工人数量
- 我切换回 ParallelGC,因为这是 Java8 中的默认设置。现在,当进行手动 GC 时,至少有 10MB 被释放。对于 GC1,什么也没有发生。但是还是两次GC都无法清理。
- 为了确定
,我从 wildfly 配置中删除了 <websockets>
- 我尝试在本地模拟它但失败了。
- 我使用 eclipseMAT 和 JXRay 分析了堆,但它只是指向一些内部 wildfly 类。
- 我将 Java 恢复到版本 8,系统仍然显示相同的行为,因此 wildfly 是最有可能的嫌疑人。
在 eclipseMAT 中也可以找到这 1544 个对象。他们都有相同的大小。
唯一起作用的是完全停用 wildfly 中的字节缓冲区。
/subsystem=io/buffer-pool=default:write-attribute(name=direct-buffers,value=false)
但是据我了解,这有性能缺陷吗?
所以有人知道问题出在哪里吗?任何其他设置/调整的提示?或者是否存在与此相关的已知 Wildfly 或 JVM 错误?
更新 1:关于 IO 线程 - 也许这个概念对我来说不是 100% 清楚。因为有 ioThreads
值
还有线程和线程池。
根据定义,可以认为每个工作线程创建的数量 ioThreads
(在我的例子中是 12)?但是在我的例子中,线程/工作者的数量似乎仍然很少......
更新 2: 我降级了 java,它仍然显示相同的行为。因此我怀疑是野蝇引起了这个问题。
可能是 Xnio 问题。看这个问题https://issues.redhat.com/browse/JBEAP-728
经过大量分析、分析等,我得出以下结论:
- OOM的原因是18.0.1版本的wildfly引起的。 19.1.0也存在(没测试20或21)
- 将
-XX:MaxDirectMemorySize
设置为 512m 或更低值时,我能够相当快地触发 OOM。我想很多人都没有遇到这个问题,因为默认情况下这个值等于 Xmx 值,这个值可能很大。使用我们的应用程序 的 ReST API 时出现问题
- 正如 Evgeny 指出的那样 XNIO is a high potential candidate 因为在分析时它缩小到(或接近)那个区域...
- 我没有时间进一步调查,所以我尝试了 wildfly 22,它正在运行。此版本使用的是最新的 xnio 包 (3.8.4)
- WF 22 中的 DirectMemory 仍然很低。大约 10mb。可以看到计数上升和下降,这在以前不是这样的
所以最后的修复是更新到 wildfly 版本 22.0.1(或更高版本)
将环境从 Wildfly 13
更新到 Wildfly 18.0.1
后,我们遇到了
A channel event listener threw an exception: java.lang.OutOfMemoryError: Direct buffer memory
at java.base/java.nio.Bits.reserveMemory(Bits.java:175)
at java.base/java.nio.DirectByteBuffer.<init>(DirectByteBuffer.java:118)
at java.base/java.nio.ByteBuffer.allocateDirect(ByteBuffer.java:317)
at org.jboss.xnio@3.7.3.Final//org.xnio.BufferAllocator.allocate(BufferAllocator.java:57)
at org.jboss.xnio@3.7.3.Final//org.xnio.BufferAllocator.allocate(BufferAllocator.java:55)
at org.jboss.xnio@3.7.3.Final//org.xnio.ByteBufferSlicePool.allocateSlices(ByteBufferSlicePool.java:162)
at org.jboss.xnio@3.7.3.Final//org.xnio.ByteBufferSlicePool.allocate(ByteBufferSlicePool.java:149)
at io.undertow.core@2.0.27.Final//io.undertow.server.XnioByteBufferPool.allocate(XnioByteBufferPool.java:53)
at io.undertow.core@2.0.27.Final//io.undertow.server.protocol.http.HttpReadListener.handleEventWithNoRunningRequest(HttpReadListener.java:147)
at io.undertow.core@2.0.27.Final//io.undertow.server.protocol.http.HttpReadListener.handleEvent(HttpReadListener.java:136)
at io.undertow.core@2.0.27.Final//io.undertow.server.protocol.http.HttpReadListener.handleEvent(HttpReadListener.java:59)
at org.jboss.xnio@3.7.3.Final//org.xnio.ChannelListeners.invokeChannelListener(ChannelListeners.java:92)
at org.jboss.xnio@3.7.3.Final//org.xnio.conduits.ReadReadyHandler$ChannelListenerHandler.readReady(ReadReadyHandler.java:66)
at org.jboss.xnio.nio@3.7.3.Final//org.xnio.nio.NioSocketConduit.handleReady(NioSocketConduit.java:89)
at org.jboss.xnio.nio@3.7.3.Final//org.xnio.nio.WorkerThread.run(WorkerThread.java:591)
应用程序方面没有任何更改。我查看了缓冲池,似乎有些资源没有被释放。我触发了几次手动 GC,但几乎没有任何反应。 (正常运行时间 2 小时)
在旧配置之前它看起来像这样(正常运行时间 >250h):
现在我做了很多研究,我能找到的最接近的东西是 post here on SO。然而,这是与 websockets 结合使用的,但是有 no websockets 在使用中。
我读了几篇(好)文章(1,2,3,
- OutOfMemoryError 发生在 5GB,因为堆是 5GB => 我将 MaxDirectMemorySize 减少到 512m,然后是 64m,但是 OOM 发生得更快
- 我设置
-Djdk.nio.maxCachedBufferSize=262144
- 我查看了IO worker的数量:96(6cpus*16),貌似比较合理。该系统通常具有短寿命线程(最大池大小为 13)。所以这不可能是我猜的工人数量
- 我切换回 ParallelGC,因为这是 Java8 中的默认设置。现在,当进行手动 GC 时,至少有 10MB 被释放。对于 GC1,什么也没有发生。但是还是两次GC都无法清理。
- 为了确定 ,我从 wildfly 配置中删除了
- 我尝试在本地模拟它但失败了。
- 我使用 eclipseMAT 和 JXRay 分析了堆,但它只是指向一些内部 wildfly 类。
- 我将 Java 恢复到版本 8,系统仍然显示相同的行为,因此 wildfly 是最有可能的嫌疑人。
<websockets>
在 eclipseMAT 中也可以找到这 1544 个对象。他们都有相同的大小。
唯一起作用的是完全停用 wildfly 中的字节缓冲区。
/subsystem=io/buffer-pool=default:write-attribute(name=direct-buffers,value=false)
但是据我了解,这有性能缺陷吗?
所以有人知道问题出在哪里吗?任何其他设置/调整的提示?或者是否存在与此相关的已知 Wildfly 或 JVM 错误?
更新 1:关于 IO 线程 - 也许这个概念对我来说不是 100% 清楚。因为有 ioThreads
值
根据定义,可以认为每个工作线程创建的数量 ioThreads
(在我的例子中是 12)?但是在我的例子中,线程/工作者的数量似乎仍然很少......
更新 2: 我降级了 java,它仍然显示相同的行为。因此我怀疑是野蝇引起了这个问题。
可能是 Xnio 问题。看这个问题https://issues.redhat.com/browse/JBEAP-728
经过大量分析、分析等,我得出以下结论:
- OOM的原因是18.0.1版本的wildfly引起的。 19.1.0也存在(没测试20或21)
- 将
-XX:MaxDirectMemorySize
设置为 512m 或更低值时,我能够相当快地触发 OOM。我想很多人都没有遇到这个问题,因为默认情况下这个值等于 Xmx 值,这个值可能很大。使用我们的应用程序 的 ReST API 时出现问题
- 正如 Evgeny 指出的那样 XNIO is a high potential candidate 因为在分析时它缩小到(或接近)那个区域...
- 我没有时间进一步调查,所以我尝试了 wildfly 22,它正在运行。此版本使用的是最新的 xnio 包 (3.8.4)
- WF 22 中的 DirectMemory 仍然很低。大约 10mb。可以看到计数上升和下降,这在以前不是这样的
所以最后的修复是更新到 wildfly 版本 22.0.1(或更高版本)