Skip to content

Commit 95c0f11

Browse files
committed
Construct StringWriter instances with appropriate initial size
Closes gh-25789
1 parent 06c76d8 commit 95c0f11

File tree

7 files changed

+60
-48
lines changed

7 files changed

+60
-48
lines changed

spring-context-support/src/main/java/org/springframework/ui/freemarker/FreeMarkerTemplateUtils.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2014 the original author or authors.
2+
* Copyright 2002-2020 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -46,7 +46,7 @@ public abstract class FreeMarkerTemplateUtils {
4646
public static String processTemplateIntoString(Template template, Object model)
4747
throws IOException, TemplateException {
4848

49-
StringWriter result = new StringWriter();
49+
StringWriter result = new StringWriter(1024);
5050
template.process(model, result);
5151
return result.toString();
5252
}

spring-core/src/main/java/org/springframework/util/FileCopyUtils.java

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2017 the original author or authors.
2+
* Copyright 2002-2020 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -40,9 +40,13 @@
4040
* @author Juergen Hoeller
4141
* @since 06.10.2003
4242
* @see StreamUtils
43+
* @see FileSystemUtils
4344
*/
4445
public abstract class FileCopyUtils {
4546

47+
/**
48+
* The default buffer size used when copying bytes.
49+
*/
4650
public static final int BUFFER_SIZE = StreamUtils.BUFFER_SIZE;
4751

4852

@@ -184,15 +188,15 @@ public static int copy(Reader in, Writer out) throws IOException {
184188
Assert.notNull(out, "No Writer specified");
185189

186190
try {
187-
int byteCount = 0;
191+
int charCount = 0;
188192
char[] buffer = new char[BUFFER_SIZE];
189-
int bytesRead = -1;
190-
while ((bytesRead = in.read(buffer)) != -1) {
191-
out.write(buffer, 0, bytesRead);
192-
byteCount += bytesRead;
193+
int charsRead;
194+
while ((charsRead = in.read(buffer)) != -1) {
195+
out.write(buffer, 0, charsRead);
196+
charCount += charsRead;
193197
}
194198
out.flush();
195-
return byteCount;
199+
return charCount;
196200
}
197201
finally {
198202
try {
@@ -209,7 +213,7 @@ public static int copy(Reader in, Writer out) throws IOException {
209213
}
210214

211215
/**
212-
* Copy the contents of the given String to the given output Writer.
216+
* Copy the contents of the given String to the given Writer.
213217
* Closes the writer when done.
214218
* @param in the String to copy from
215219
* @param out the Writer to copy to

spring-core/src/main/java/org/springframework/util/StreamUtils.java

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2017 the original author or authors.
2+
* Copyright 2002-2020 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -43,14 +43,17 @@
4343
*/
4444
public abstract class StreamUtils {
4545

46+
/**
47+
* The default buffer size used when copying bytes.
48+
*/
4649
public static final int BUFFER_SIZE = 4096;
4750

4851
private static final byte[] EMPTY_CONTENT = new byte[0];
4952

5053

5154
/**
5255
* Copy the contents of the given InputStream into a new byte array.
53-
* Leaves the stream open when done.
56+
* <p>Leaves the stream open when done.
5457
* @param in the stream to copy from (may be {@code null} or empty)
5558
* @return the new byte array that has been copied to (possibly empty)
5659
* @throws IOException in case of I/O errors
@@ -67,8 +70,9 @@ public static byte[] copyToByteArray(InputStream in) throws IOException {
6770

6871
/**
6972
* Copy the contents of the given InputStream into a String.
70-
* Leaves the stream open when done.
73+
* <p>Leaves the stream open when done.
7174
* @param in the InputStream to copy from (may be {@code null} or empty)
75+
* @param charset the {@link Charset} to use to decode the bytes
7276
* @return the String that has been copied to (possibly empty)
7377
* @throws IOException in case of I/O errors
7478
*/
@@ -77,19 +81,19 @@ public static String copyToString(InputStream in, Charset charset) throws IOExce
7781
return "";
7882
}
7983

80-
StringBuilder out = new StringBuilder();
84+
StringBuilder out = new StringBuilder(BUFFER_SIZE);
8185
InputStreamReader reader = new InputStreamReader(in, charset);
8286
char[] buffer = new char[BUFFER_SIZE];
83-
int bytesRead = -1;
84-
while ((bytesRead = reader.read(buffer)) != -1) {
85-
out.append(buffer, 0, bytesRead);
87+
int charsRead;
88+
while ((charsRead = reader.read(buffer)) != -1) {
89+
out.append(buffer, 0, charsRead);
8690
}
8791
return out.toString();
8892
}
8993

9094
/**
9195
* Copy the contents of the given byte array to the given OutputStream.
92-
* Leaves the stream open when done.
96+
* <p>Leaves the stream open when done.
9397
* @param in the byte array to copy from
9498
* @param out the OutputStream to copy to
9599
* @throws IOException in case of I/O errors
@@ -99,19 +103,20 @@ public static void copy(byte[] in, OutputStream out) throws IOException {
99103
Assert.notNull(out, "No OutputStream specified");
100104

101105
out.write(in);
106+
out.flush();
102107
}
103108

104109
/**
105-
* Copy the contents of the given String to the given output OutputStream.
106-
* Leaves the stream open when done.
110+
* Copy the contents of the given String to the given OutputStream.
111+
* <p>Leaves the stream open when done.
107112
* @param in the String to copy from
108113
* @param charset the Charset
109114
* @param out the OutputStream to copy to
110115
* @throws IOException in case of I/O errors
111116
*/
112117
public static void copy(String in, Charset charset, OutputStream out) throws IOException {
113118
Assert.notNull(in, "No input String specified");
114-
Assert.notNull(charset, "No charset specified");
119+
Assert.notNull(charset, "No Charset specified");
115120
Assert.notNull(out, "No OutputStream specified");
116121

117122
Writer writer = new OutputStreamWriter(out, charset);
@@ -121,7 +126,7 @@ public static void copy(String in, Charset charset, OutputStream out) throws IOE
121126

122127
/**
123128
* Copy the contents of the given InputStream to the given OutputStream.
124-
* Leaves both streams open when done.
129+
* <p>Leaves both streams open when done.
125130
* @param in the InputStream to copy from
126131
* @param out the OutputStream to copy to
127132
* @return the number of bytes copied
@@ -133,7 +138,7 @@ public static int copy(InputStream in, OutputStream out) throws IOException {
133138

134139
int byteCount = 0;
135140
byte[] buffer = new byte[BUFFER_SIZE];
136-
int bytesRead = -1;
141+
int bytesRead;
137142
while ((bytesRead = in.read(buffer)) != -1) {
138143
out.write(buffer, 0, bytesRead);
139144
byteCount += bytesRead;
@@ -165,7 +170,7 @@ public static long copyRange(InputStream in, OutputStream out, long start, long
165170
}
166171

167172
long bytesToCopy = end - start + 1;
168-
byte[] buffer = new byte[StreamUtils.BUFFER_SIZE];
173+
byte[] buffer = new byte[(int) Math.min(StreamUtils.BUFFER_SIZE, bytesToCopy)];
169174
while (bytesToCopy > 0) {
170175
int bytesRead = in.read(buffer);
171176
if (bytesRead == -1) {
@@ -185,7 +190,7 @@ else if (bytesRead <= bytesToCopy) {
185190

186191
/**
187192
* Drain the remaining content of the given InputStream.
188-
* Leaves the InputStream open when done.
193+
* <p>Leaves the InputStream open when done.
189194
* @param in the InputStream to drain
190195
* @return the number of bytes read
191196
* @throws IOException in case of I/O errors
@@ -255,7 +260,7 @@ public NonClosingOutputStream(OutputStream out) {
255260
@Override
256261
public void write(byte[] b, int off, int let) throws IOException {
257262
// It is critical that we override this method for performance
258-
out.write(b, off, let);
263+
this.out.write(b, off, let);
259264
}
260265

261266
@Override

spring-jms/src/main/java/org/springframework/jms/support/converter/MappingJackson2MessageConverter.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2016 the original author or authors.
2+
* Copyright 2002-2020 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -117,7 +117,7 @@ public void setTargetType(MessageType targetType) {
117117
/**
118118
* Specify the encoding to use when converting to and from text-based
119119
* message body content. The default encoding will be "UTF-8".
120-
* <p>When reading from a a text-based message, an encoding may have been
120+
* <p>When reading from a text-based message, an encoding may have been
121121
* suggested through a special JMS property which will then be preferred
122122
* over the encoding set on this MessageConverter instance.
123123
* @see #setEncodingPropertyName
@@ -283,13 +283,13 @@ protected TextMessage mapToTextMessage(Object object, Session session, ObjectMap
283283
* @return the resulting message
284284
* @throws JMSException if thrown by JMS methods
285285
* @throws IOException in case of I/O errors
286-
* @see Session#createBytesMessage
287286
* @since 4.3
287+
* @see Session#createBytesMessage
288288
*/
289289
protected TextMessage mapToTextMessage(Object object, Session session, ObjectWriter objectWriter)
290290
throws JMSException, IOException {
291291

292-
StringWriter writer = new StringWriter();
292+
StringWriter writer = new StringWriter(1024);
293293
objectWriter.writeValue(writer, object);
294294
return session.createTextMessage(writer.toString());
295295
}
@@ -386,7 +386,7 @@ protected Message mapToMessage(Object object, Session session, ObjectWriter obje
386386
* sets the resulting value (either a mapped id or the raw Java class name)
387387
* into the configured type id message property.
388388
* @param object the payload object to set a type id for
389-
* @param message the JMS Message to set the type id on
389+
* @param message the JMS Message on which to set the type id property
390390
* @throws JMSException if thrown by JMS methods
391391
* @see #getJavaTypeForMessage(javax.jms.Message)
392392
* @see #setTypeIdPropertyName(String)
@@ -482,7 +482,7 @@ protected Object convertFromMessage(Message message, JavaType targetJavaType)
482482
* <p>The default implementation parses the configured type id property name
483483
* and consults the configured type id mapping. This can be overridden with
484484
* a different strategy, e.g. doing some heuristics based on message origin.
485-
* @param message the JMS Message to set the type id on
485+
* @param message the JMS Message from which to get the type id property
486486
* @throws JMSException if thrown by JMS methods
487487
* @see #setTypeIdOnMessage(Object, javax.jms.Message)
488488
* @see #setTypeIdPropertyName(String)

spring-jms/src/main/java/org/springframework/jms/support/converter/MarshallingMessageConverter.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2014 the original author or authors.
2+
* Copyright 2002-2020 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -46,8 +46,6 @@
4646
* @author Arjen Poutsma
4747
* @author Juergen Hoeller
4848
* @since 3.0
49-
* @see org.springframework.jms.core.JmsTemplate#convertAndSend
50-
* @see org.springframework.jms.core.JmsTemplate#receiveAndConvert
5149
*/
5250
public class MarshallingMessageConverter implements MessageConverter, InitializingBean {
5351

@@ -210,7 +208,7 @@ else if (message instanceof BytesMessage) {
210208
protected TextMessage marshalToTextMessage(Object object, Session session, Marshaller marshaller)
211209
throws JMSException, IOException, XmlMappingException {
212210

213-
StringWriter writer = new StringWriter();
211+
StringWriter writer = new StringWriter(1024);
214212
Result result = new StreamResult(writer);
215213
marshaller.marshal(object, result);
216214
return session.createTextMessage(writer.toString());

spring-messaging/src/main/java/org/springframework/messaging/converter/MappingJackson2MessageConverter.java

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2018 the original author or authors.
2+
* Copyright 2002-2020 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -140,12 +140,13 @@ private void configurePrettyPrint() {
140140
}
141141
}
142142

143+
143144
@Override
144145
protected boolean canConvertFrom(Message<?> message, Class<?> targetClass) {
145146
if (targetClass == null || !supportsMimeType(message.getHeaders())) {
146147
return false;
147148
}
148-
JavaType javaType = this.objectMapper.constructType(targetClass);
149+
JavaType javaType = this.objectMapper.getTypeFactory().constructType(targetClass);
149150
AtomicReference<Throwable> causeRef = new AtomicReference<Throwable>();
150151
if (this.objectMapper.canDeserialize(javaType, causeRef)) {
151152
return true;
@@ -221,6 +222,7 @@ protected Object convertFromInternal(Message<?> message, Class<?> targetClass, O
221222
}
222223
}
223224
else {
225+
// Assuming a text-based source payload
224226
if (view != null) {
225227
return this.objectMapper.readerWithView(view).forType(javaType).readValue(payload.toString());
226228
}
@@ -243,10 +245,9 @@ private JavaType getJavaType(Class<?> targetClass, Object conversionHint) {
243245
}
244246
Type genericParameterType = param.getNestedGenericParameterType();
245247
Class<?> contextClass = param.getContainingClass();
246-
Type type = getJavaType(genericParameterType, contextClass);
247-
return this.objectMapper.getTypeFactory().constructType(type);
248+
return getJavaType(genericParameterType, contextClass);
248249
}
249-
return this.objectMapper.constructType(targetClass);
250+
return this.objectMapper.getTypeFactory().constructType(targetClass);
250251
}
251252

252253
private JavaType getJavaType(Type type, Class<?> contextClass) {
@@ -329,7 +330,8 @@ protected Object convertToInternal(Object payload, MessageHeaders headers, Objec
329330
payload = out.toByteArray();
330331
}
331332
else {
332-
Writer writer = new StringWriter();
333+
// Assuming a text-based target payload
334+
Writer writer = new StringWriter(1024);
333335
if (view != null) {
334336
this.objectMapper.writerWithView(view).writeValue(writer, payload);
335337
}
@@ -387,7 +389,7 @@ private Class<?> extractViewClass(JsonView annotation, Object conversionHint) {
387389
* @return the JSON encoding to use (never {@code null})
388390
*/
389391
protected JsonEncoding getJsonEncoding(MimeType contentType) {
390-
if ((contentType != null) && (contentType.getCharset() != null)) {
392+
if (contentType != null && contentType.getCharset() != null) {
391393
Charset charset = contentType.getCharset();
392394
for (JsonEncoding encoding : JsonEncoding.values()) {
393395
if (charset.name().equals(encoding.getJavaName())) {

spring-messaging/src/main/java/org/springframework/messaging/converter/MarshallingMessageConverter.java

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2017 the original author or authors.
2+
* Copyright 2002-2020 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -45,6 +45,8 @@
4545
*
4646
* @author Arjen Poutsma
4747
* @since 4.2
48+
* @see Marshaller
49+
* @see Unmarshaller
4850
*/
4951
public class MarshallingMessageConverter extends AbstractMessageConverter {
5052

@@ -58,7 +60,8 @@ public class MarshallingMessageConverter extends AbstractMessageConverter {
5860
* {@link #setUnmarshaller(Unmarshaller)} to be invoked separately.
5961
*/
6062
public MarshallingMessageConverter() {
61-
this(new MimeType("application", "xml"), new MimeType("text", "xml"), new MimeType("application", "*+xml"));
63+
this(new MimeType("application", "xml"), new MimeType("text", "xml"),
64+
new MimeType("application", "*+xml"));
6265
}
6366

6467
/**
@@ -154,7 +157,7 @@ private Source getSource(Object payload) {
154157
return new StreamSource(new ByteArrayInputStream((byte[]) payload));
155158
}
156159
else {
157-
return new StreamSource(new StringReader((String) payload));
160+
return new StreamSource(new StringReader(payload.toString()));
158161
}
159162
}
160163

@@ -163,13 +166,13 @@ protected Object convertToInternal(Object payload, MessageHeaders headers, Objec
163166
Assert.notNull(this.marshaller, "Property 'marshaller' is required");
164167
try {
165168
if (byte[].class == getSerializedPayloadClass()) {
166-
ByteArrayOutputStream out = new ByteArrayOutputStream();
169+
ByteArrayOutputStream out = new ByteArrayOutputStream(1024);
167170
Result result = new StreamResult(out);
168171
this.marshaller.marshal(payload, result);
169172
payload = out.toByteArray();
170173
}
171174
else {
172-
Writer writer = new StringWriter();
175+
Writer writer = new StringWriter(1024);
173176
Result result = new StreamResult(writer);
174177
this.marshaller.marshal(payload, result);
175178
payload = writer.toString();

0 commit comments

Comments
 (0)