【发布时间】:2018-11-28 21:38:21
【问题描述】:
几天前我问(并回答了自己)this question 并解决了问题,但我不太明白为什么问题已解决,并希望得到一些澄清.
基本上,我已经实现了一个基于 jax-rs 的 REST 服务,该服务从 RavenDB 数据库中检索信息并以流的形式返回该内容。我遇到的问题是一个未关闭的数据库结果迭代器,这导致 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,它应该在我的方法完成时超出范围/变得不可访问状态为 400 或 200 - 因此收集垃圾。
要明确一点:我当然不是建议不应该正确关闭打开的连接等 - 我现在正在这样做 - 或者依靠 Java 的垃圾收集机制来拯救我们免于懒惰/不干净的编码......我我只是在努力理解那些未关闭的迭代器是如何导致观察到的 Tomcat 行为的。
事实上,我的假设是我们甚至不需要知道迭代器实现的细节,因为在 Java 的“银河级”对象生命周期中,实现差异是无关紧要的。 => “一旦一个对象变得无法访问,它的编码方式就无关紧要了”。 我唯一能想象的是,Tomcat 以某种方式(通过其容器机制?)稍微改变了这里的游戏,并导致事情“徘徊”。 有人可以解释一下吗?
提前致谢!
【问题讨论】:
标签: java tomcat garbage-collection jax-rs database-connection