Skip to content

Commit e526d22

Browse files
committed
PDFBOX-5169: reduce the memory footprint by reusing the internal byte array instead of copying it
git-svn-id: https://svn.apache.org/repos/asf/pdfbox/trunk@1930286 13f79535-47bb-0310-9956-ffa450edef68
1 parent 322675f commit e526d22

File tree

1 file changed

+25
-8
lines changed

1 file changed

+25
-8
lines changed

pdfbox/src/main/java/org/apache/pdfbox/pdfwriter/compress/COSWriterObjectStream.java

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -113,22 +113,22 @@ public COSStream writeObjectsToStream(COSStream stream) throws IOException
113113
stream.setInt(COSName.N, objectCount);
114114
// Prepare the compressible objects for writing.
115115
List<Long> objectNumbers = new ArrayList<>(objectCount);
116-
List<byte[]> objectsBuffer = new ArrayList<>(objectCount);
116+
List<ByteArrayOutputStream> objectsBuffer = new ArrayList<>(objectCount);
117117
for (int i = 0; i < objectCount; i++)
118118
{
119-
try (ByteArrayOutputStream partialOutput = new ByteArrayOutputStream())
119+
try (ByteArrayOutputStream partialOutput = new DirectAccessByteArrayOutputStream())
120120
{
121121
objectNumbers.add(preparedKeys.get(i).getNumber());
122122
COSBase base = preparedObjects.get(i);
123123
writeObject(partialOutput, base, true);
124-
objectsBuffer.add(partialOutput.toByteArray());
124+
objectsBuffer.add(partialOutput);
125125
}
126126
}
127127

128128
// Deduce the object stream byte offset map.
129129
byte[] offsetsMapBuffer;
130130
long nextObjectOffset = 0;
131-
try (ByteArrayOutputStream partialOutput = new ByteArrayOutputStream())
131+
try (ByteArrayOutputStream partialOutput = new DirectAccessByteArrayOutputStream())
132132
{
133133
for (int i = 0; i < objectNumbers.size(); i++)
134134
{
@@ -138,7 +138,7 @@ public COSStream writeObjectsToStream(COSStream stream) throws IOException
138138
partialOutput.write(
139139
String.valueOf(nextObjectOffset).getBytes(StandardCharsets.ISO_8859_1));
140140
partialOutput.write(COSWriter.SPACE);
141-
nextObjectOffset += objectsBuffer.get(i).length;
141+
nextObjectOffset += objectsBuffer.get(i).size();
142142
}
143143
offsetsMapBuffer = partialOutput.toByteArray();
144144
}
@@ -148,9 +148,9 @@ public COSStream writeObjectsToStream(COSStream stream) throws IOException
148148
{
149149
output.write(offsetsMapBuffer);
150150
stream.setInt(COSName.FIRST, offsetsMapBuffer.length);
151-
for (byte[] rawObject : objectsBuffer)
151+
for (ByteArrayOutputStream rawObject : objectsBuffer)
152152
{
153-
output.write(rawObject);
153+
output.write(rawObject.toByteArray());
154154
}
155155
}
156156
return stream;
@@ -384,7 +384,24 @@ private void writeObjectReference(OutputStream output, COSObjectKey indirectRefe
384384
*/
385385
private void writeCOSNull(OutputStream output) throws IOException
386386
{
387-
output.write("null".getBytes(StandardCharsets.ISO_8859_1));
387+
output.write(COSNull.NULL_BYTES);
388388
output.write(COSWriter.SPACE);
389389
}
390+
391+
/**
392+
* Reuse the underlying byte array instead of copying it.
393+
*
394+
* This is a private class as reusing the byte array may have some unwanted side effects.
395+
*
396+
*/
397+
private class DirectAccessByteArrayOutputStream extends ByteArrayOutputStream
398+
{
399+
400+
@Override
401+
public byte[] toByteArray()
402+
{
403+
return buf;
404+
}
405+
}
406+
390407
}

0 commit comments

Comments
 (0)