简体   繁体   English

Apache MINA 不删除未使用的数据

[英]Apache MINA does not remove unused data

I have a little problem about my MINA client.我的 MINA 客户端有点问题。

I create only one connection to server, then the server sends some sort of data in every second periodically.我只创建一个到服务器的连接,然后服务器每秒定期发送某种数据。

In short, client connects to the server;简而言之,客户端连接到服务器; server sends back a string to the client and all those steps use the same opened connection (same client object and client handler).服务器向客户端发回一个字符串,所有这些步骤都使用相同的打开连接(相同的客户端 object 和客户端处理程序)。

But the problem is, I think, the old data is not collected by GC.但问题是,我认为,旧数据不是由 GC 收集的。 The used heap is getting larger in seconds and never decreases.使用的堆在几秒钟内变大并且永远不会减少。 My messageReceived method is empty !我的 messageReceived 方法是空的!

public void messageReceived(IoSession session, Object message) { }

Any idea?任何想法?

VisualVM itself causes a lot of garbage. VisualVM本身会造成大量垃圾。 You can start an empty application and sleep the thread, enable VisualVM and watch the garbage start to collect. 您可以启动一个空的应用程序并使线程休眠,启用VisualVM并观察垃圾回收。 WITH NO CODE. 没有代码。

I am however, seeing a similar issue where mina is not retaining but generating long run items that are never garbage collected (unless you run a Full GC). 但是,我遇到了类似的问题,其中mina不会保留,而是会生成永远不会进行垃圾回收的长期运行项(除非您运行Full GC)。 This problem can cause an application with real memory of 4mb to show up as 80mb over an hour. 此问题可能导致实际内存为4mb的应用程序在一个小时内显示为80mb。 It never gets collected. 它永远不会被收集。

I am about to build my own framework to wrap NIO because I could never keep a server online for long periods without restarts like this. 我将建立自己的框架来包装NIO,因为如果没有这样的重启,我将无法长时间保持服务器在线。

If it never decreases, enable -XX:+HeapDumpOnOutOfMemoryError and you will get a heap dump on an out of memory error. 如果它永远不会减少,请启用-XX:+HeapDumpOnOutOfMemoryError ,您将在发生内存不足错误时得到堆转储。

The amount of memory used is not important, only how much is retained after a full GC. 使用的内存量并不重要,仅在完整GC后保留多少内存即可。 I suggest you run VisualVM and tirgger a full GC periodically and see how much free after this. 我建议您运行VisualVM并定期触发一个完整的GC,然后查看多少可用空间。

Here we are in 2023 with Apache Mina 2.2.1 and I ran into the same issue.我们在 2023 年使用 Apache Mina 2.2.1,我遇到了同样的问题。 Deployed software as a service and looked this morning to see it was using 9.6GB of memory after running for about a week!将软件部署为服务,今天早上看到它在运行大约一周后使用了 9.6GB 的 memory!

I profiled it with VisualVM to find that the Objects being decoded were never being garbage collected: Turns out there's two fixes to this problem:我使用 VisualVM 对其进行了分析,发现正在解码的对象从未被垃圾收集:原来有两个解决此问题的方法:

  1. You have your IoSession set to use the read operation but you don't actually need it:您已将 IoSession 设置为使用读取操作,但实际上并不需要它:
// Set this to false if you don't require ReadFuture!
session.getConfig().setUseReadOperation(false);
  1. If you require asynchronous reading then you must call read on your session or it will cache all inbound messages until they are "read":如果您需要异步读取,那么您必须在 session 上调用 read,否则它将缓存所有入站消息,直到它们被“读取”:
public void messageReceived(IoSession ioSession, Object message) { 
   ReadFuture future = ioSession.read();
        future.awaitUninterruptibly();
        future.getMessage();

}

In the Javadocs foundhere , under the read method, they state:此处找到的 Javadocs 中,在 read 方法下,它们是 state:

a ReadFuture which is notified when a new message is received, the connection is closed or an exception is caught.一个 ReadFuture,当收到新消息、关闭连接或捕获异常时收到通知。 This operation is especially useful when you implement a client application.当您实现客户端应用程序时,此操作特别有用。 TODO: Describe here how we enable this feature. TODO:在这里描述我们如何启用此功能。 However, please note that this operation is disabled by default and throw IllegalStateException because all received events must be queued somewhere to support this operation, possibly leading to memory leak.但是请注意,默认情况下此操作是禁用的并抛出 IllegalStateException,因为所有接收到的事件都必须在某处排队以支持此操作,可能导致 memory 泄漏。 This means you have to keep calling read() once you enabled this operation.这意味着您必须在启用此操作后继续调用 read()。 To enable this operation, please call IoSessionConfig.setUseReadOperation(boolean) with true.要启用此操作,请使用 true 调用 IoSessionConfig.setUseReadOperation(boolean)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM