如果 JsonGenerator 是在 ByteArrayOutputStream 之上创建的,那么关闭它是否有意义
Does it make sense to close JsonGenerator if it was created on top of ByteArrayOutputStream
假设我想创建 JSON 并使用 Java JSON 流 API 将其存储在字符串中。为此,我在其上创建了 ByteArrayOutputStream (BAOS) 和 JsonGenerator。
ByteArrayOutputStream collector = new ByteArrayOutputStream();
JsonGenerator jsonGenerator = Json.createGenerator(collector);
一段时间后,当我完成它时,我从 BAOS 中获取 String 并应该释放所有资源。如下来自BAOSclose方法实现
public void close() throws IOException {
}
它什么都不做。 close JsonGenerator 的方法,然而,它不仅关闭了底层流,而且还刷新了缓冲区并回收了一个缓冲池(说实话,我不知道后者是什么意思)。
我怀疑 JsonGenerator 在将数据写入 BAOS 时会缓冲数据。但是,我需要一些时间来进一步调查它,所以我希望有人已经知道:关闭生成器是否有意义。
备注
我使用 javax.json.
的 Glassfish 实现
我认为无论底层实现如何,在完成资源时关闭资源总是有意义的。没有说未来实现不会改变,如果处理不当可能会导致资源泄漏。
如果您使用的是 Java 7 或更高版本,类 都将实现 Closeable
。为什么不直接将它们放在 try-with-resources 中?
try (ByteArrayOutputStream collector = new ByteArrayOutputStream();
JsonGenerator jsonGenerator = Json.createGenerator(collector)) {
// your implementation here
} catch (IOException e) {
// handle exceptions
}
不需要 Java 7 之前的样板代码,您可以确保所有资源都已正确关闭。
好的。我检查了 JsonGeneratorImpl 源代码。我不得不说我真的需要关闭它。首先,JsonGeneratorImpl 在此处从 BufferPoolImpl 接收缓冲区:
public final char[] take() {
char[] t = (char[])getQueue().poll();
if (t == null)
return new char[4096];
return t;
}
当我们调用 close 时,我们把它放回去:
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());
}
假设我想创建 JSON 并使用 Java JSON 流 API 将其存储在字符串中。为此,我在其上创建了 ByteArrayOutputStream (BAOS) 和 JsonGenerator。
ByteArrayOutputStream collector = new ByteArrayOutputStream();
JsonGenerator jsonGenerator = Json.createGenerator(collector);
一段时间后,当我完成它时,我从 BAOS 中获取 String 并应该释放所有资源。如下来自BAOSclose方法实现
public void close() throws IOException {
}
它什么都不做。 close JsonGenerator 的方法,然而,它不仅关闭了底层流,而且还刷新了缓冲区并回收了一个缓冲池(说实话,我不知道后者是什么意思)。
我怀疑 JsonGenerator 在将数据写入 BAOS 时会缓冲数据。但是,我需要一些时间来进一步调查它,所以我希望有人已经知道:关闭生成器是否有意义。
备注
我使用 javax.json.
我认为无论底层实现如何,在完成资源时关闭资源总是有意义的。没有说未来实现不会改变,如果处理不当可能会导致资源泄漏。
如果您使用的是 Java 7 或更高版本,类 都将实现 Closeable
。为什么不直接将它们放在 try-with-resources 中?
try (ByteArrayOutputStream collector = new ByteArrayOutputStream();
JsonGenerator jsonGenerator = Json.createGenerator(collector)) {
// your implementation here
} catch (IOException e) {
// handle exceptions
}
不需要 Java 7 之前的样板代码,您可以确保所有资源都已正确关闭。
好的。我检查了 JsonGeneratorImpl 源代码。我不得不说我真的需要关闭它。首先,JsonGeneratorImpl 在此处从 BufferPoolImpl 接收缓冲区:
public final char[] take() {
char[] t = (char[])getQueue().poll();
if (t == null)
return new char[4096];
return t;
}
当我们调用 close 时,我们把它放回去:
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());
}