假设我想创建JSON并使用Java JSON Streaming API将其存储在String中。为此,我在它上面创建了ByteArrayOutputStream(BAOS)和JsonGenerator。
ByteArrayOutputStream collector = new ByteArrayOutputStream();
JsonGenerator jsonGenerator = Json.createGenerator(collector);
过了一会儿,当我完成它之后,我从BAOS中取出String并且应该释放所有资源。如下来自BAOS close 方法实现
public void close() throws IOException {
}
它什么都不做。然而,JsonGenerator的 close 方法不仅会关闭底层流,还会刷新缓冲区并回收缓冲池(坦率地说,我不知道后者是什么意思)。
我怀疑JsonGenerator在将数据写入BAOS时会缓冲数据。但是,我需要花一些时间进一步调查,所以我希望有人已经知道:关闭发电机是否有意义,或者不是。
注意
我使用了javax.json的Glassfish实现。
答案 0 :(得分:2)
确定。我检查了JsonGeneratorImpl源代码。我不得不说我真的需要关闭它。首先,JsonGeneratorImpl从BufferPoolImpl接收缓冲区:
public final char[] take() {
char[] t = (char[])getQueue().poll();
if (t == null)
return new char[4096];
return t;
}
当我们打电话给关闭时,我们把它放回去了:
public final void recycle(char[] t)
{
getQueue().offer(t);
}
如果你像我所说的那样创建jsonGenerator,那就没有多大意义了:
JsonGenerator jsonGenerator = Json.createGenerator(collector);
因为在这种情况下,每个新创建的生成器将使用自己的JsonProvider实例,以及它自己的缓冲池实例,当我完成使用生成器时,它将由GC收集。因此,最好创建JsonGeneratorFactory,因为此工厂创建的所有生成器都将共享公共缓冲池。是的 - 在这种情况下,最后关闭发电机真的更好 关闭生成器的另一个原因是 close 方法调用 flushBuffer 方法。是的,无论输出流类型如何,生成器都使用缓冲区:
void writeChar(char c) {
if (this.len >= this.buf.length) {
flushBuffer();
}
this.buf[(this.len++)] = c;
}
所以最终答案是是。最终关闭JsonGenerator总是有意义的
的更新强>
正如@StephenC正确地指出的那样,关闭它还有另一个原因,因为它强制检查未完成的JSON:
if ((this.currentContext.scope != Scope.IN_NONE) || (this.currentContext.first)) {
throw new JsonGenerationException(JsonMessages.GENERATOR_INCOMPLETE_JSON());
}
答案 1 :(得分:1)
我认为在资源完成时关闭资源总是有意义的,无论底层实现如何。没有什么说未来的实施不会改变,如果处理不当,可能会导致资源泄漏。
如果您使用的是Java 7或更高版本,则这两个类都会实现Closeable
。为什么不把它们放在试用资源中呢?
try (ByteArrayOutputStream collector = new ByteArrayOutputStream();
JsonGenerator jsonGenerator = Json.createGenerator(collector)) {
// your implementation here
} catch (IOException e) {
// handle exceptions
}
不需要Java 7样板前代码,您可以确保所有资源都已正确关闭。