当前位置: 首页 > 知识库问答 >
问题:

ConcurrentLinkedQueue$Node对象中的内存泄漏

梁丘飞鸾
2023-03-14

我有一个系统,其中许多线程产生的日志将被插入到一个NoSql后端。为了减少网络流量,我在服务器和后端之间引入了一个缓冲区。

环境是:

Java,JSP,Spring MVC,JDK 1.7 Apache-tomcat-6

使用的缓冲区是java中的ConcurrentLinkedQueue。还实现了一个DBPushThread来每5秒从队列中获取日志,并将它们插入backened。我们使用offer()进行插入,使用poll()进行弹出。根据poll()的javadoc-https://docs . Oracle . com/javase/7/docs/API/Java/util/concurrentlinkedqueue . html # poll(),它将检索元素并更新队列头。所以这个节点永远不会被引用,最终会被垃圾回收。

附加代码片段

public void add(Log log) {
        buffer.offer(log);
    }

从队列中检索内容(此处最大索引始终指定为队列大小)

public List<Log> getContents(int maxIndex) {
    List<Log> logs = new LinkedList<Log>();

    for (int i = 0; i < maxIndex; i++) {
        Log log = buffer.poll();
        logs.add(Log);
    }
    return logs;
}

我只做了缓冲区(这是单例队列)作为实例变量。所有其他函数都是函数的本地范围。

JDK 1.7的一个错误是废弃的节点永远不会被垃圾收集?

运筹学

我需要在ConcurrentLinkedQueue中实现对象池吗?如果有,我该如何实现?

运筹学

是我代码的错误吗?

请指导。

共有2个答案

丰岳
2023-03-14

正如8472所指出的,分析了转储,发现这不是ConcurrentLinkedQueue的poll()和offer()方法的问题。

在我们的架构中,concurrentLinkedQueue 充当缓冲区,日志堆积在其中,DBPushThread 将从 CL 队列中获取日志并将它们插入后端存储。使用的后端是弹性搜索。

由于elasticsearch的间歇性稳定性/伸缩性问题,日志到elastic search的DBPushThread插入失败并引发异常。我们抛出了那个异常。因为它是thread,所以它将是一个UnCaughtException,父线程永远不会得到通知。

所以很多日志被注入到CL队列中,但没有从CL队列中轮询任何日志(因为DBPushThread死亡)。通过处理弹性搜索问题并在向弹性搜索插入数据时捕获异常,我们能够解决这个问题。

我们监控系统大约一个月,内存占用是一致的。感谢8472给我指引了正确的方向

史懿轩
2023-03-14

在检查实例视图时,我可以看到LinkedList节点值(属性“项目”),并且对于大多数对象,它对下一个节点(属性“下一个”)的引用设置为null。

不,那些是传出引用。相反,您应该检查对这些对象的传入引用。有东西抓住了它们。

从您的屏幕截图来看,它实际上看起来像CLQ的头部和尾部指向实例#5,这让我想知道所有其他节点实例都是由什么引用的。

通常,您必须分析GC根的路径,以找到对象上的内容。

CLQ使这个问题复杂化,因为它懒惰地更新/清除一些指针,这些指针在并发访问下可能会失败,但稍后应该得到清理,即它们不应该继续堆积。

您还应该检查堆转储分析器是否显示“浮动垃圾”,即符合收集条件但尚未收集的对象。如果是这样的话,你可能找错树了。

 类似资料:
  • 我尝试用一个大表(大约一万条记录)中的记录填充JdbcRowSet。我尝试了两个变体(参见下面的代码): 创建连接对象,使用JdbcRowSetImpl(connection)实例化,在循环中执行查询。 使用JdbcRowSetImpl(DriverManager.GetConnection(“jdbc:....”)实例化,在循环中执行查询。 第一个变体会导致内存泄漏,直到堆满为止。第二个变体没有

  • 我有内存泄漏,我知道它在哪里(我想是这样的),但我不知道为什么会发生。负载测试以下endpoint(使用服务器)时发生内存泄漏: 我非常肯定对象没有被(垃圾回收器)释放。在每一个请求中,应用程序使用的内存都在增长。我做了一些附加测试: 因此,在每个请求中,我都将big object分配给对象作为其属性。我观察到,有了这个附加属性,内存增长得快得多。在60秒内每完成1000个请求,内存会增加100M

  • 我有一个在Tomcat7上运行的web应用程序的问题。 当我尝试重新启动web应用程序时,我在servlet内部创建的线程打开的端口仍然是打开的。 “http-bio-8080-acceptor-0”后台进程prio=10 tid=0x00007F4ED4206000 nid=0x71f0 runnable[0x00007F4ECC78F000]java.lang.thread.state:run

  • 我在Tomcat中得到了threadlocal内存泄漏错误,我正在使用ThreadPool,但在我的WebApp中没有threadlocal的实现。 严重:web应用程序[/mywebapp]创建了一个ThreadLocal,其键类型为[org.a pache.http.impl.cookie.dateformatholder$1](值为[org.apache.http.imp l.cookie.

  • 本文向大家介绍浅析Java中的内存泄漏,包括了浅析Java中的内存泄漏的使用技巧和注意事项,需要的朋友参考一下 ava最明显的一个优势就是它的内存管理机制。你只需简单创建对象,java的垃圾回收机制负责分配和释放内存。然而情况并不像想像的那么简单,因为在Java应用中经常发生内存泄漏。 本教程演示了什么是内存泄漏,为什么会发生内存泄漏以及如何预防内存泄漏。 什么是内存泄漏? 定义:如果对象在应用中

  • 当关闭Tomcat时,我得到以下错误: 严重:web应用程序[App]创建了一个ThreadLocal,其键类型为[org.apache.logging.log4j.core.layout.PatternLayout$1](值为[org.apache.logging.log4j.core.layout.PatternLayout$1@14391AAF]),值类型为[java.lang.String