内存泄漏将lambda提交给带有复制列表的线程

时间:2018-06-10 21:04:30

标签: java multithreading memory-leaks guava

我有一些简单的代码,用于轮询专用线程中的消息,在列表中对它们进行批处理,然后将所述列表传递给不同的线程,以便执行涉及阻塞的操作。这是一个简化的粗略近似值:

class MessageProcessor extends MessagePoller implements Runnable {

  private final ExecutorService batchHandlerExec = Executors.newSingleThreadExecutor(); 
  private final List<Operation> operations = new ArrayList();

  //just to indicate this is a thread started somewhere
  public void run() { while(true) processMessage(); }

  public void processMessage() {
    Message msg = poll();

    operations.add(Operation.buildFrom(msg));

    if(operations.size() >= SOME_NUMBER) {
      List<Operations> batch = ImmutableCopy.copyOf(operations);

      batchHandlerExec.submit(() -> doSomethingBlockingWith(batch));

      operations.clear(); 
    }
  }
}

所以有两个线程,一个消费消息,另一个消息。问题是,给定几天,这些线程将停止运行(虽然没有弹簧死亡,但我使用弹簧启动)

长话短说,我怀疑内存泄漏导致我的MessageProcessor死机,而我正在分析堆转储等等,如果有人能指出我在这段代码上可能遗漏的任何内容,那将非常有用。特别是:

  • 我认为Operation未被收集,clear()是否有效?我使用Guava ImmutableList副本而不释放它,但我认为它会被收集,因为doSomethingBlockingWith()在做了它做的任何事情后都会超出范围
  • 我的真实执行者服务也是singleThreadExecutor,所以也许我可以将更多的工作添加到它可以处理的submit()(批处理可能比处理它们更快),那是什么填充堆?

我已经使用 jvisualvm 并分析了一下,启用了详细的垃圾收集器,使用了jmap和东西,但所有信息对我来说似乎都很神秘。到目前为止,我的堆似乎总是充满了字符串,长篇和似乎由Operation持有的东西,但我不知道。任何帮助表示赞赏

0 个答案:

没有答案