• ByteArrayInputStream.flush() is no-op method along with ByteArrayInputStream.close(), ByteArrayOutputStream.flush() and ByteArrayOutputStream.close(). So we can drop try-with-resources statements as well as explicit calls to flush()/close()
  • new String(BAOS.toByteArray(), charset) replaced with call to StreamUtils.baosToString(baos, charset) to swallow UnsupportedEncodingException which is actually never thrown as charset is already available at invocation point

As of performance I've used more precise benchmark:

@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@Fork(jvmArgsAppend = {"-Xms2g", "-Xmx2g", "-XX:+UseParallelGC"})
public class ByteArrayOutputStreamBenchmark {

  @Benchmark
  public String toString(Data data) throws UnsupportedEncodingException {
    return data.baos.toString(data.charset.name());
  }

  @Benchmark
  public String newString(Data data) {
    return new String(data.baos.toByteArray(), data.charset);
  }

  @Benchmark
  public String toString_noCS(Data data) {
    return data.baos.toString();
  }

  @Benchmark
  public String newString_noCS(Data data) {
    return new String(data.baos.toByteArray());
  }

  @State(Scope.Thread)
  public static class Data {

    @Param({"0", "10", "100", "1000"})
    private int length;

    private final Charset charset = Charset.defaultCharset();

    private ByteArrayOutputStream baos;

    @Setup
    public void setup() throws IOException {
      byte[] bytes = StringUtils.repeat('a', length).getBytes(charset);

      baos = new ByteArrayOutputStream(length);
      baos.write(bytes);
    }
  }

}

Which demonstrates improvement in both time and memory consumption

JDK 8
                                       (length)  Mode      Score     Error   Units

newString                                     0  avgt     66.084 ±   2.121   ns/op
toString                                      0  avgt     44.601 ±   0.656   ns/op
newString_noCS                                0  avgt     69.694 ±   1.949   ns/op
toString_noCS                                 0  avgt     43.758 ±   0.333   ns/op

newString                                    10  avgt     53.232 ±   1.569   ns/op
toString                                     10  avgt     45.151 ±   0.397   ns/op
newString_noCS                               10  avgt     52.005 ±   0.473   ns/op
toString_noCS                                10  avgt     45.657 ±   4.325   ns/op

newString                                   100  avgt     96.067 ±   1.466   ns/op
toString                                    100  avgt     77.924 ±   0.645   ns/op
newString_noCS                              100  avgt     94.716 ±   3.138   ns/op
toString_noCS                               100  avgt     80.460 ±   1.375   ns/op

newString                                  1000  avgt    667.188 ±  33.071   ns/op
toString                                   1000  avgt    511.302 ±   1.730   ns/op
newString_noCS                             1000  avgt    624.721 ±  20.786   ns/op
toString_noCS                              1000  avgt    530.833 ±  11.087   ns/op

newString:·gc.alloc.rate.norm                 0  avgt     96.000 ±   0.001    B/op
toString:·gc.alloc.rate.norm                  0  avgt     40.000 ±   0.001    B/op
newString_noCS:·gc.alloc.rate.norm            0  avgt     56.000 ±   0.001    B/op
toString_noCS:·gc.alloc.rate.norm             0  avgt     40.000 ±   0.001    B/op

newString:·gc.alloc.rate.norm                10  avgt    136.000 ±   0.001    B/op
toString:·gc.alloc.rate.norm                 10  avgt     64.000 ±   0.001    B/op
newString_noCS:·gc.alloc.rate.norm           10  avgt     96.000 ±   0.001    B/op
toString_noCS:·gc.alloc.rate.norm            10  avgt     64.000 ±   0.001    B/op

newString:·gc.alloc.rate.norm               100  avgt    400.000 ±   0.001    B/op
toString:·gc.alloc.rate.norm                100  avgt    240.000 ±   0.001    B/op
newString_noCS:·gc.alloc.rate.norm          100  avgt    360.000 ±   0.001    B/op
toString_noCS:·gc.alloc.rate.norm           100  avgt    240.000 ±   0.001    B/op

newString:·gc.alloc.rate.norm              1000  avgt   3096.001 ±   0.001    B/op
toString:·gc.alloc.rate.norm               1000  avgt   2040.001 ±   0.001    B/op
newString_noCS:·gc.alloc.rate.norm         1000  avgt   3056.001 ±   0.001    B/op
toString_noCS:·gc.alloc.rate.norm          1000  avgt   2040.001 ±   0.001    B/op

Comment From: sbrannen

For future reference, please make sure you execute ./gradlew check prior to submitting a PR in order to avoid errors such as the following.

> Task :spring-core:checkstyleMain FAILED
[ant:checkstyle] [ERROR] /source/spring-framework/spring-core/src/main/java/org/springframework/util/StreamUtils.java:249:20: Javadoc element descriptions should not start with an uppercase letter. [SpringJavadoc]
[ant:checkstyle] [ERROR] /source/spring-framework/spring-core/src/main/java/org/springframework/util/StreamUtils.java:256:17: '}' at column 3 should be alone on a line. [RightCurly]
[ant:checkstyle] [ERROR] /source/spring-framework/spring-core/src/main/java/org/springframework/util/StreamUtils.java:256:55: Single letter catch variable (use "ex" instead). [SpringCatch]

Comment From: stsypanov

@sbrannen let me push once again ))

Comment From: sbrannen

I've already begun a local merge process.

So no need to push again.

Comment From: stsypanov

Ok, I was unaware about ./gradlew check, thanks for pointing that out!

Comment From: sbrannen

This has been merged into master in e63d1cf12df785d07867a09370b8e9d76dcc0c99 and further revised in 9e30620ac2a3dc5e3e963b637434667a50be2190.

Thanks