Optimize Jackson resource management in codecs

Prior to this commit, references to `JsonGenerator` and
`ByteArrayBuilder` were not closed/released within codecs calls.
This prevents Jackson from reusing more efficiently shared memory
resources.

This commit properly closes/releases Jackson resources in Spring MVC,
Spring WebFlux and Spring Messaging codecs.
A benchmark on WebFlux codecs (in both single value/streaming mode)
shows significant throughput and allocation improvements for small
payloads.

Closes gh-25910
This commit is contained in:
Brian Clozel
2020-10-20 15:36:23 +02:00
parent db3d537e72
commit 7bee3d1574
5 changed files with 67 additions and 52 deletions

View File

@@ -206,29 +206,30 @@ public abstract class AbstractJackson2View extends AbstractView {
* @throws IOException if writing failed
*/
protected void writeContent(OutputStream stream, Object object) throws IOException {
JsonGenerator generator = this.objectMapper.getFactory().createGenerator(stream, this.encoding);
writePrefix(generator, object);
try (JsonGenerator generator = this.objectMapper.getFactory().createGenerator(stream, this.encoding)) {
writePrefix(generator, object);
Object value = object;
Class<?> serializationView = null;
FilterProvider filters = null;
Object value = object;
Class<?> serializationView = null;
FilterProvider filters = null;
if (value instanceof MappingJacksonValue) {
MappingJacksonValue container = (MappingJacksonValue) value;
value = container.getValue();
serializationView = container.getSerializationView();
filters = container.getFilters();
if (value instanceof MappingJacksonValue) {
MappingJacksonValue container = (MappingJacksonValue) value;
value = container.getValue();
serializationView = container.getSerializationView();
filters = container.getFilters();
}
ObjectWriter objectWriter = (serializationView != null ?
this.objectMapper.writerWithView(serializationView) : this.objectMapper.writer());
if (filters != null) {
objectWriter = objectWriter.with(filters);
}
objectWriter.writeValue(generator, value);
writeSuffix(generator, object);
generator.flush();
}
ObjectWriter objectWriter = (serializationView != null ?
this.objectMapper.writerWithView(serializationView) : this.objectMapper.writer());
if (filters != null) {
objectWriter = objectWriter.with(filters);
}
objectWriter.writeValue(generator, value);
writeSuffix(generator, object);
generator.flush();
}