Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/364.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 有没有一种方法可以用我的CompletableFuture代码解决这个内存泄漏问题?_Java_Completable Future - Fatal编程技术网

Java 有没有一种方法可以用我的CompletableFuture代码解决这个内存泄漏问题?

Java 有没有一种方法可以用我的CompletableFuture代码解决这个内存泄漏问题?,java,completable-future,Java,Completable Future,在http1.1中,我们有一个服务器可以进行背压(是的,它关闭了套接字,如果我们在负载下,客户端实际上会冻结等待……这非常好)。我们在http2中也这样做,而http2规范没有在http2引擎中进行背压(即,我们不需要背压,但我们遵循规范,它还关闭插座)。当我说“关闭”时,我的意思是它取消注册,这样我们就停止读取nic,nic缓冲区填充,然后客户端nic填充,直到他冻结 无论如何,我们遇到了一个有趣的问题,并且一直在努力解决它,而不出现内存泄漏。我们最近的迭代是这样的 public Comple

在http1.1中,我们有一个服务器可以进行背压(是的,它关闭了套接字,如果我们在负载下,客户端实际上会冻结等待……这非常好)。我们在http2中也这样做,而http2规范没有在http2引擎中进行背压(即,我们不需要背压,但我们遵循规范,它还关闭插座)。当我说“关闭”时,我的意思是它取消注册,这样我们就停止读取nic,nic缓冲区填充,然后客户端nic填充,直到他冻结

无论如何,我们遇到了一个有趣的问题,并且一直在努力解决它,而不出现内存泄漏。我们最近的迭代是这样的

public CompletableFuture<Void> runLoop(List<T> newData, Session session, Processor<T> processFunction) {
    
    //All the below futures must be chained with previous ones in case previous ones are not
    //done which will serialize it all to be in sequence
    CompletableFuture<Void> future = session.getProcessFuture();
    
    for(T data : newData) {
        //VERY IMPORTANT: Writing the code like this would slam through calling process N times
        //BUT it doesn't give the clients a chance to set a flag between packets
        //Mainly done for exceptions and streaming so you can log exc, set a boolean so you
        //don't get 100 exceptions while something is happening like socket disconnect
        //In these 2 lines of code, processCorrectly is CALLED N times RIGHT NOW
        //The code below this only calls them right now IF AND ONLY IF the client returns
        //a completed future each time!!!
        //CompletableFuture<Void> messageFuture = processFunction.process(data);
        //future = future.thenCompose( f -> messageFuture);
        
        future = future.thenCompose( voidd -> processFunction.process(data));
    }
    
    session.setProcessFuturee(future);
    
    return future;
}
然后,我意识到如果等待我的原始代码会怎么样。这就是事情变得奇怪的地方。它只下降到196MB并保持不变。我不知道为什么,也不知道引用的是什么。我真的没有在MAT(eclipse)中看到任何东西,或者我用错了那个工具

我是否有内存泄漏?我对最后的结果感到困惑。它应该至少降低到<20MB

编辑(回答沙多夫的回答):我相信返回的未来不会与它的来源联系在一起。可以说,这是链条的“尾巴”。但事实恰恰相反,创造它的未来与之相连,因此当创造它的未来完成时,它可以解决这个未来。因此,在我看来,我每次都会在会话中发布列表的尾部(而不是创建越来越长的链)。期货的真正问题在于引用它的线程以及它是否得到了解决。这意味着唯一剩下的引用它的是解析它的匿名Runnable。一旦发生这种情况,它应该能够解决

完全的未来甚至不是内存(MAT eclipse)

天哪,又一重大发现。。如果我把这行注释掉

  • future.complete(空)

然后,程序永远飞起来,内存在180MB和6MB之间跳跃。

这方面不是很好,但你正在构建越来越大的未来,而且永远不会停止——不管列表的大小,它只会消耗越来越多的内存,永远不会释放它

您将看到您是否在测试中执行以下操作:

chain.runLoop(列表,s,p);
if(queue.size()==0){
System.out.println(“队列为空”);
s、 setProcessFuturee(CompletableFuture.completedFuture(null));
rt.gc();
}

因此,我认为您需要使用不同的工具,
CompletableFuture
可能不够强大。也许是一些成熟的反应库,比如rxjava或reactor?

好的,我做了一个git推送和git提交。没有内存泄漏。现在发生的事情是,我们使劲地猛击主线程,所有线程都在累积……。当给时间来解决问题时,内存会回到6MB。这只需要很长的时间,但是日志帮助我看到了这一点,最重要的是,我错过了关键点的runtime.gc()调用


所以,有了背压,我们应该没有问题了,因为这使得所有的期货在增加负荷之前都会解决。

谢谢您的尝试!我用一些似乎有用的东西编辑了这篇文章。我自己也在努力理解“锁链”。我编辑了我文章的底部以包含细节,以防你好奇。OMG。如果我注释掉future.complete(null),它“完成了未来”,那么就不会有内存问题,循环会在180MB和6MB之间反复跳转。到底发生了什么事?
public CompletableFuture<Void> runLoop(List<T> newData, Session session, Processor<T> processFunction) {
    
    //All the below futures must be chained with previous ones in case previous ones are not
    //done which will serialize it all to be in sequence
    CompletableFuture<Void> future = session.getProcessFuture();
    
    CompletableFuture<Void> newFuture = new CompletableFuture<Void>(); 
            
    for(T data : newData) {
        //VERY IMPORTANT: Writing the code like this would slam through calling process N times
        //BUT it doesn't give the clients a chance to seet a flag between packets
        //Mainly done for exceptions and streaming so you can log exc, set a boolean so you
        //don't get 100 exceptions while something is happening like socket disconnect
        //In these 2 lines of code, processCorrectly is CALLED N times RIGHT NOW
        //The code below this only calls them right now IF AND ONLY IF the client returns
        //a completed future each time!!!
        
        //This seems to have memory issues as well....
        //CompletableFuture<Void> temp = processFunction.process(data);
        //future = future.thenCompose(f -> temp);
        
        future = future.thenCompose( voidd -> processFunction.process(data));
    }
    
    future.handle((voidd, t) -> {
        if(t != null) {
            newFuture.completeExceptionally(t);
            return 0;
        }
        
        newFuture.complete(null);
        return 0;
    });
    
    //comment this out and memory leak goes away of course.......
    session.setProcessFuturee(newFuture);
    
    return newFuture;
}
future = future.thenComposeAsync( voidd -> processFunction.process(data), executor );