关闭JAX RS客户端/响应

Ale*_*ndr 6 java memory-leaks jax-rs

目前尚不清楚是否必须关闭JAX RS Client / Response实例。如果必须,是否总是?

根据有关Client类的文档

调用此方法将有效地使客户端实例产生的所有资源目标无效。

WebTarget类没有任何invalidate()/ close()方法,但是Response类具有。根据文件

关闭基础消息实体输入流(如果可用并打开),并释放与响应关联的任何其他资源(例如,缓冲的消息实体数据)。

...应该在包含未使用的实体输入流的所有实例上调用close()方法,以确保正确清理与该实例关联的资源并防止潜在的内存泄漏。这是典型的客户端方案,在该方案中,应用程序层代码仅处理响应头,而忽略响应实体。

最后一段对我来说不清楚。“未消费的实体输入流”是什么意思?如果我从响应中获得InputSteam或String,是否应该显式关闭响应?

我们可以获得响应结果而无需访问Response实例:

Client client = ...;
WebTarget webTarget = ...;
Invocation.Builder builder = webTarget.request(MediaType.APPLICATION_JSON_TYPE);
Invocation invocation = builder.buildGet();
InputStream reso = invocation.invoke(InputStream.class);
Run Code Online (Sandbox Code Playgroud)

我正在使用RESTeasy实施,并且我希望响应将在resteasy实施内关闭,但我找不到它。谁能告诉我为什么?我知道Response类将实现Closeable接口, 但是即使知道使用Response,也不会关闭它。

Ada*_*ent 4

根据文档close()是幂等的。

该操作是幂等的,即它可以被多次调用并具有相同的效果,这也意味着在已经关闭的消息实例上调用 close() 方法是合法的并且不会产生进一步的影响。

所以你可以安全地关闭InputStream自己和应该的。

话虽如此,我的风格明智地不会这样做,invocation.invoke(InputStream.class)因为它invoker(Class)是为进行实体转换而设计的。相反,如果您需要 InputStream,您可能应该直接调用invocation.invoke()并处理该Response对象,因为在读取流之前您可能需要一些标头信息。在处理响应时需要标头的原因InputStream很典型,因为您要么不关心主体,要么主体需要特殊的处理和大小考虑,这正是文档所暗示的(例如HEAD对 ping 服务器的请求)。

另请参阅链接

从此方法返回的消息实例将被缓存,以供后续通过 getEntity() 检索。除非提供的实体类型是输入流,否则此方法会自动关闭未使用的原始响应实体数据流(如果打开)。如果实体数据已被缓冲,则在消耗缓冲数据之前将重置缓冲区,以便随后对此响应调用 readEntity(...) 方法。

因此,如果您选择除此之外的任何其他内容,InputStream则不必关闭Response(但无论如何这样做都是安全的,因为它是幂等的)。