Tomcat 和垃圾收集数据库连接

Tomcat and garbage collecting database connections

我前两天问过(然后自己回答),解决了问题,但是我不太明白为什么问题解决了并希望得到一些澄清。

本质上,我已经实现了一个基于 jax-rs 的 REST 服务,该服务从 RavenDB 数据库中检索信息并 returns 流中的内容。我遇到的问题是一个未关闭的数据库结果迭代器,它导致 REST 服务在恰好 10 个请求后挂起(并且不再接受进一步的请求)。

我的代码大致如下:

public Response ...
    {
        (...)

        StreamingOutput adminAreaStream = new StreamingOutput()
        {
            ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter();

            @Override
            public void write(OutputStream output) throws IOException, WebApplicationException
            {
                try(IDocumentSession currentSession = ServiceListener.ravenDBStore.openSession())
                {
                    Writer writer = new BufferedWriter(new OutputStreamWriter(output));
                    (...)   
                    CloseableIterator<StreamResult<AdministrativeArea>> results;
                    (...)
                    writer.flush();
                    writer.close();
                    results.close();
                    currentSession.advanced().clear();
                    currentSession.close();
                }
                catch (Exception e)
                {
                    System.out.println("Exception: " + e.getMessage() + e.getStackTrace());
                }
            }
        };
        if(!requestIsValid)
            return Response.status(400).build();
        else
            return Response.ok(adminAreaStream).build();
    }

根据我对 Java 中对象生命周期的理解,或者更具体地说,对象可达性和垃圾收集,即使我没有正确关闭 CleasableIterator,它也应该退出 scope/become 在我的方法以 400 或 200 状态结束时无法访问 - 因此得到垃圾收集。

明确一点:我当然不是建议人们不应该正确关闭打开的连接等 - 我现在正在这样做 - 或者依靠 Java 的垃圾收集机制来拯救我们lazy/unclean 编码......我只是在努力理解那些未关闭的迭代器是如何导致观察到的 Tomcat 行为的。

事实上,我的假设是我们甚至不需要知道有关迭代器实现的细节,因为在 Java 对象生命周期的 "galactic level" 处,实现差异是无关紧要的。 => "Once an object has become unreachable, it doesn't matter exactly how it was coded"。 我唯一能想到的是 Tomcat 以某种方式(通过它的容器机制?),稍微改变了这里的游戏,并导致事情变成 "hang around"。 有人可以解释一下吗?

提前致谢!

CloseableIterator 指的是 CloseableHttpResponse,后者指的是 HTTP 连接。当 CloseableIterator 不再可达时,终结器不会释放响应或连接。您造成了连接泄漏。您的错误类似于此处描述的错误:https://phillbarber.blogspot.com/2014/02/lessons-learned-from-connection-leak-in.html

在这里查看为什么释放资源的终结方法不是一个好主意:https://www.baeldung.com/java-finalize