This is an automated email from the ASF dual-hosted git repository.

tallison pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tika.git


The following commit(s) were added to refs/heads/main by this push:
     new 9cbe0c990 use commons-io byte streams (#671)
9cbe0c990 is described below

commit 9cbe0c990ba6fd226d7d78d4ff0fcabf087dd26a
Author: PJ Fanning <[email protected]>
AuthorDate: Wed Sep 14 19:11:25 2022 +0100

    use commons-io byte streams (#671)
---
 .../org/apache/tika/detect/XmlRootExtractor.java   |  4 +-
 .../org/apache/tika/embedder/ExternalEmbedder.java |  4 +-
 .../org/apache/tika/fork/ClassLoaderProxy.java     | 15 +++---
 .../apache/tika/fork/ForkObjectInputStream.java    |  6 +--
 .../fork/RecursiveMetadataContentHandlerProxy.java |  8 +--
 .../java/org/apache/tika/io/TikaInputStream.java   |  4 +-
 .../main/java/org/apache/tika/mime/MagicMatch.java |  5 +-
 .../main/java/org/apache/tika/mime/MimeTypes.java  |  5 +-
 .../java/org/apache/tika/mime/MimeTypesReader.java |  4 +-
 .../java/org/apache/tika/pipes/PipesClient.java    | 18 +++----
 .../java/org/apache/tika/pipes/PipesServer.java    | 10 ++--
 .../apache/tika/utils/RereadableInputStream.java   |  4 +-
 .../java/org/apache/tika/utils/XMLReaderUtils.java | 63 ++++++++++++++++++++++
 .../tika/eval/core/util/ContentTagParser.java      |  4 +-
 .../org/apache/tika/fuzzing/pdf/EvilCOSWriter.java | 17 ++++--
 .../org/apache/tika/parser/gdal/GDALParser.java    |  5 +-
 .../java/org/apache/tika/parser/hdf/HDFParser.java |  4 +-
 .../captioning/tf/TensorflowRESTCaptioner.java     |  4 +-
 .../tika/parser/pot/PooledTimeSeriesParser.java    | 30 +++++------
 .../recognition/tf/TensorflowRESTRecogniser.java   |  4 +-
 .../apache/tika/parser/journal/TEIDOMParser.java   |  6 +--
 .../org/apache/tika/parser/video/FLVParser.java    | 35 ++++++------
 .../org/apache/tika/parser/html/DataURIScheme.java |  5 +-
 .../org/apache/tika/parser/html/HtmlHandler.java   |  4 +-
 .../tika/parser/image/ImageMetadataExtractor.java  |  4 +-
 .../org/apache/tika/parser/image/PSDParser.java    |  4 +-
 .../apache/tika/parser/jdbc/JDBCTableReader.java   |  4 +-
 .../tika/parser/mail/MailContentHandler.java       | 14 ++---
 .../org/apache/tika/parser/mbox/MboxParser.java    |  8 ++-
 .../microsoft/MSEmbeddedStreamTranslator.java      | 20 +++----
 .../tika/parser/microsoft/JackcessExtractor.java   |  4 +-
 .../apache/tika/parser/microsoft/OfficeParser.java |  6 +--
 .../tika/parser/microsoft/OutlookExtractor.java    |  8 +--
 .../tika/parser/microsoft/chm/ChmExtractor.java    |  4 +-
 .../tika/parser/microsoft/chm/ChmParser.java       |  4 +-
 .../onenote/OneNoteLegacyDumpStrings.java          | 10 ++--
 .../ooxml/xwpf/ml2006/BinaryDataHandler.java       |  4 +-
 .../parser/microsoft/rtf/RTFEmbObjHandler.java     |  6 +--
 .../parser/microsoft/rtf/RTFObjDataParser.java     | 14 ++---
 .../java/org/apache/tika/parser/dbf/DBFCell.java   |  4 +-
 .../apache/tika/parser/pdf/AbstractPDF2XHTML.java  |  6 +--
 .../tika/parser/pdf/PDFEncodedStringDecoder.java   |  4 +-
 .../java/org/apache/tika/parser/pdf/PDFParser.java |  4 +-
 .../tika/parser/pdf/image/ImageGraphicsEngine.java |  4 +-
 .../org/apache/tika/parser/pkg/PackageParser.java  |  7 +--
 .../org/apache/tika/parser/txt/CharsetMatch.java   |  4 +-
 .../apache/tika/parser/xml/FictionBookParser.java  |  9 ++--
 .../apache/tika/parser/xmp/JempboxExtractor.java   |  7 ++-
 .../detect/zip/DefaultZipContainerDetector.java    |  6 +--
 .../tika/detect/zip/OpenDocumentDetector.java      |  8 +--
 .../apache/tika/detect/zip/StarOfficeDetector.java |  7 ++-
 .../tika/pipes/emitter/azblob/AZBlobEmitter.java   | 15 +++---
 .../apache/tika/pipes/emitter/gcs/GCSEmitter.java  | 24 +++++----
 .../pipes/emitter/opensearch/OpenSearchClient.java |  4 +-
 .../apache/tika/pipes/emitter/s3/S3Emitter.java    |  4 +-
 .../tika/pipes/fetcher/http/HttpFetcher.java       |  6 +--
 .../org/apache/tika/client/HttpClientUtil.java     |  3 +-
 .../tika/server/client/TikaPipesHttpClient.java    |  5 +-
 58 files changed, 293 insertions(+), 220 deletions(-)

diff --git 
a/tika-core/src/main/java/org/apache/tika/detect/XmlRootExtractor.java 
b/tika-core/src/main/java/org/apache/tika/detect/XmlRootExtractor.java
index 2d093cd65..61fcedbe9 100644
--- a/tika-core/src/main/java/org/apache/tika/detect/XmlRootExtractor.java
+++ b/tika-core/src/main/java/org/apache/tika/detect/XmlRootExtractor.java
@@ -16,13 +16,13 @@
  */
 package org.apache.tika.detect;
 
-import java.io.ByteArrayInputStream;
 import java.io.CharConversionException;
 import java.io.InputStream;
 import java.util.Arrays;
 import javax.xml.namespace.QName;
 
 import org.apache.commons.io.input.CloseShieldInputStream;
+import org.apache.commons.io.input.UnsynchronizedByteArrayInputStream;
 import org.xml.sax.Attributes;
 import org.xml.sax.SAXException;
 import org.xml.sax.helpers.DefaultHandler;
@@ -43,7 +43,7 @@ public class XmlRootExtractor {
         // this loop should be very rare
         while (true) {
             try {
-                return extractRootElement(new ByteArrayInputStream(data), 
true);
+                return extractRootElement(new 
UnsynchronizedByteArrayInputStream(data), true);
             } catch (MalformedCharException e) {
                 // see TIKA-3596, try to handle truncated/bad encoded XML files
                 int newLen = data.length / 2;
diff --git 
a/tika-core/src/main/java/org/apache/tika/embedder/ExternalEmbedder.java 
b/tika-core/src/main/java/org/apache/tika/embedder/ExternalEmbedder.java
index 40d8df795..bc8331807 100644
--- a/tika-core/src/main/java/org/apache/tika/embedder/ExternalEmbedder.java
+++ b/tika-core/src/main/java/org/apache/tika/embedder/ExternalEmbedder.java
@@ -18,7 +18,6 @@ package org.apache.tika.embedder;
 
 import static java.nio.charset.StandardCharsets.UTF_8;
 
-import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
@@ -32,6 +31,7 @@ import java.util.Map;
 import java.util.Set;
 
 import org.apache.commons.io.IOUtils;
+import org.apache.commons.io.output.UnsynchronizedByteArrayOutputStream;
 
 import org.apache.tika.exception.TikaException;
 import org.apache.tika.io.TemporaryResources;
@@ -404,7 +404,7 @@ public class ExternalEmbedder implements Embedder {
             process = Runtime.getRuntime().exec(cmd.toArray(new String[]{}));
         }
 
-        ByteArrayOutputStream stdErrOutputStream = new ByteArrayOutputStream();
+        UnsynchronizedByteArrayOutputStream stdErrOutputStream = new 
UnsynchronizedByteArrayOutputStream();
 
         try {
             sendStdErrToOutputStream(process, stdErrOutputStream);
diff --git a/tika-core/src/main/java/org/apache/tika/fork/ClassLoaderProxy.java 
b/tika-core/src/main/java/org/apache/tika/fork/ClassLoaderProxy.java
index 792b6cb03..968ad8096 100644
--- a/tika-core/src/main/java/org/apache/tika/fork/ClassLoaderProxy.java
+++ b/tika-core/src/main/java/org/apache/tika/fork/ClassLoaderProxy.java
@@ -139,14 +139,15 @@ class ClassLoaderProxy extends ClassLoader implements 
ForkProxy {
     }
 
     private byte[] readStream() throws IOException {
-        ByteArrayOutputStream stream = new ByteArrayOutputStream();
-        byte[] buffer = new byte[0xffff];
-        int n;
-        while ((n = input.readUnsignedShort()) > 0) {
-            input.readFully(buffer, 0, n);
-            stream.write(buffer, 0, n);
+        try (ByteArrayOutputStream stream = new ByteArrayOutputStream()) {
+            byte[] buffer = new byte[0xffff];
+            int n;
+            while ((n = input.readUnsignedShort()) > 0) {
+                input.readFully(buffer, 0, n);
+                stream.write(buffer, 0, n);
+            }
+            return stream.toByteArray();
         }
-        return stream.toByteArray();
     }
 
 }
diff --git 
a/tika-core/src/main/java/org/apache/tika/fork/ForkObjectInputStream.java 
b/tika-core/src/main/java/org/apache/tika/fork/ForkObjectInputStream.java
index ce776b8af..61e2dae48 100644
--- a/tika-core/src/main/java/org/apache/tika/fork/ForkObjectInputStream.java
+++ b/tika-core/src/main/java/org/apache/tika/fork/ForkObjectInputStream.java
@@ -67,9 +67,9 @@ class ForkObjectInputStream extends ObjectInputStream {
      */
     public static void sendObject(Object object, DataOutputStream output) 
throws IOException {
         ByteArrayOutputStream buffer = new ByteArrayOutputStream();
-        ObjectOutputStream serializer = new ObjectOutputStream(buffer);
-        serializer.writeObject(object);
-        serializer.close();
+        try (ObjectOutputStream serializer = new ObjectOutputStream(buffer)) {
+            serializer.writeObject(object);
+        }
 
         byte[] data = buffer.toByteArray();
         output.writeInt(data.length);
diff --git 
a/tika-core/src/main/java/org/apache/tika/fork/RecursiveMetadataContentHandlerProxy.java
 
b/tika-core/src/main/java/org/apache/tika/fork/RecursiveMetadataContentHandlerProxy.java
index 02673f8f3..348c33d92 100644
--- 
a/tika-core/src/main/java/org/apache/tika/fork/RecursiveMetadataContentHandlerProxy.java
+++ 
b/tika-core/src/main/java/org/apache/tika/fork/RecursiveMetadataContentHandlerProxy.java
@@ -136,10 +136,10 @@ class RecursiveMetadataContentHandlerProxy extends 
RecursiveParserWrapperHandler
         //when I try to use ForkedObjectInputStream, but
         //not when I do this manually ?!
         ByteArrayOutputStream bos = new ByteArrayOutputStream();
-        ObjectOutputStream oos = new ObjectOutputStream(bos);
-        oos.writeObject(object);
-        oos.flush();
-        oos.close();
+        try (ObjectOutputStream oos = new ObjectOutputStream(bos)) {
+            oos.writeObject(object);
+            oos.flush();
+        }
         return bos.toByteArray();
 
     }
diff --git a/tika-core/src/main/java/org/apache/tika/io/TikaInputStream.java 
b/tika-core/src/main/java/org/apache/tika/io/TikaInputStream.java
index f10dc4ebc..aef9021b3 100644
--- a/tika-core/src/main/java/org/apache/tika/io/TikaInputStream.java
+++ b/tika-core/src/main/java/org/apache/tika/io/TikaInputStream.java
@@ -19,7 +19,6 @@ package org.apache.tika.io;
 import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
 
 import java.io.BufferedInputStream;
-import java.io.ByteArrayInputStream;
 import java.io.Closeable;
 import java.io.File;
 import java.io.FileInputStream;
@@ -38,6 +37,7 @@ import java.sql.Blob;
 import java.sql.SQLException;
 
 import org.apache.commons.io.input.TaggedInputStream;
+import org.apache.commons.io.input.UnsynchronizedByteArrayInputStream;
 
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.metadata.TikaCoreProperties;
@@ -300,7 +300,7 @@ public class TikaInputStream extends TaggedInputStream {
      */
     public static TikaInputStream get(byte[] data, Metadata metadata) {
         metadata.set(Metadata.CONTENT_LENGTH, Integer.toString(data.length));
-        return new TikaInputStream(new ByteArrayInputStream(data), new 
TemporaryResources(),
+        return new TikaInputStream(new 
UnsynchronizedByteArrayInputStream(data), new TemporaryResources(),
                 data.length);
     }
 
diff --git a/tika-core/src/main/java/org/apache/tika/mime/MagicMatch.java 
b/tika-core/src/main/java/org/apache/tika/mime/MagicMatch.java
index 8d29b9f3b..afa0de91f 100644
--- a/tika-core/src/main/java/org/apache/tika/mime/MagicMatch.java
+++ b/tika-core/src/main/java/org/apache/tika/mime/MagicMatch.java
@@ -16,9 +16,10 @@
  */
 package org.apache.tika.mime;
 
-import java.io.ByteArrayInputStream;
 import java.io.IOException;
 
+import org.apache.commons.io.input.UnsynchronizedByteArrayInputStream;
+
 import org.apache.tika.detect.MagicDetector;
 import org.apache.tika.metadata.Metadata;
 
@@ -56,7 +57,7 @@ class MagicMatch implements Clause {
 
     public boolean eval(byte[] data) {
         try {
-            return getDetector().detect(new ByteArrayInputStream(data), new 
Metadata()) !=
+            return getDetector().detect(new 
UnsynchronizedByteArrayInputStream(data), new Metadata()) !=
                     MediaType.OCTET_STREAM;
         } catch (IOException e) {
             // Should never happen with a ByteArrayInputStream
diff --git a/tika-core/src/main/java/org/apache/tika/mime/MimeTypes.java 
b/tika-core/src/main/java/org/apache/tika/mime/MimeTypes.java
index bb42201ea..40e4d33af 100644
--- a/tika-core/src/main/java/org/apache/tika/mime/MimeTypes.java
+++ b/tika-core/src/main/java/org/apache/tika/mime/MimeTypes.java
@@ -18,7 +18,6 @@ package org.apache.tika.mime;
 
 // JDK imports
 
-import java.io.ByteArrayInputStream;
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
@@ -33,6 +32,8 @@ import java.util.Locale;
 import java.util.Map;
 import javax.xml.namespace.QName;
 
+import org.apache.commons.io.input.UnsynchronizedByteArrayInputStream;
+
 import org.apache.tika.Tika;
 import org.apache.tika.detect.Detector;
 import org.apache.tika.detect.TextDetector;
@@ -289,7 +290,7 @@ public final class MimeTypes implements Detector, 
Serializable {
         // Finally, assume plain text if no control bytes are found
         try {
             TextDetector detector = new TextDetector(getMinLength());
-            ByteArrayInputStream stream = new ByteArrayInputStream(data);
+            UnsynchronizedByteArrayInputStream stream = new 
UnsynchronizedByteArrayInputStream(data);
             MimeType type = forName(detector.detect(stream, new 
Metadata()).toString());
             return Collections.singletonList(type);
         } catch (Exception e) {
diff --git a/tika-core/src/main/java/org/apache/tika/mime/MimeTypesReader.java 
b/tika-core/src/main/java/org/apache/tika/mime/MimeTypesReader.java
index c4e3b9d81..76bc5c752 100644
--- a/tika-core/src/main/java/org/apache/tika/mime/MimeTypesReader.java
+++ b/tika-core/src/main/java/org/apache/tika/mime/MimeTypesReader.java
@@ -16,7 +16,6 @@
  */
 package org.apache.tika.mime;
 
-import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.URI;
@@ -36,6 +35,7 @@ import javax.xml.transform.TransformerException;
 import javax.xml.transform.dom.DOMSource;
 import javax.xml.transform.sax.SAXResult;
 
+import org.apache.commons.io.input.UnsynchronizedByteArrayInputStream;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.w3c.dom.Document;
@@ -254,7 +254,7 @@ public class MimeTypesReader extends DefaultHandler 
implements MimeTypesReaderMe
 
     @Override
     public InputSource resolveEntity(String publicId, String systemId) {
-        return new InputSource(new ByteArrayInputStream(new byte[0]));
+        return new InputSource(new UnsynchronizedByteArrayInputStream(new 
byte[0]));
     }
 
     @Override
diff --git a/tika-core/src/main/java/org/apache/tika/pipes/PipesClient.java 
b/tika-core/src/main/java/org/apache/tika/pipes/PipesClient.java
index 94cd40a5f..97b86a741 100644
--- a/tika-core/src/main/java/org/apache/tika/pipes/PipesClient.java
+++ b/tika-core/src/main/java/org/apache/tika/pipes/PipesClient.java
@@ -22,8 +22,6 @@ import static org.apache.tika.pipes.PipesServer.STATUS.READY;
 import static org.apache.tika.pipes.PipesServer.STATUS.lookup;
 import static org.apache.tika.pipes.PipesServer.TIMEOUT_EXIT_CODE;
 
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
 import java.io.Closeable;
 import java.io.DataInputStream;
 import java.io.DataOutputStream;
@@ -41,6 +39,8 @@ import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 import java.util.concurrent.atomic.AtomicInteger;
 
+import org.apache.commons.io.input.UnsynchronizedByteArrayInputStream;
+import org.apache.commons.io.output.UnsynchronizedByteArrayOutputStream;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -147,7 +147,7 @@ public class PipesClient implements Closeable {
         long start = System.currentTimeMillis();
         FutureTask<PipesResult> futureTask = new FutureTask<>(() -> {
 
-            ByteArrayOutputStream bos = new ByteArrayOutputStream();
+            UnsynchronizedByteArrayOutputStream bos = new 
UnsynchronizedByteArrayOutputStream();
             try (ObjectOutputStream objectOutputStream = new 
ObjectOutputStream(bos)) {
                 objectOutputStream.writeObject(t);
             }
@@ -331,7 +331,7 @@ public class PipesClient implements Closeable {
         byte[] bytes = new byte[length];
         input.readFully(bytes);
         try (ObjectInputStream objectInputStream = new ObjectInputStream(
-                new ByteArrayInputStream(bytes))) {
+                new UnsynchronizedByteArrayInputStream(bytes))) {
             EmitData emitData = (EmitData) objectInputStream.readObject();
 
             String stack = getStack(emitData);
@@ -385,7 +385,7 @@ public class PipesClient implements Closeable {
         output = new DataOutputStream(process.getOutputStream());
 
         //wait for ready signal
-        final ByteArrayOutputStream bos = new ByteArrayOutputStream();
+        final UnsynchronizedByteArrayOutputStream bos = new 
UnsynchronizedByteArrayOutputStream();
         FutureTask<Integer> futureTask = new FutureTask<>(() -> {
             int b = input.read();
             int read = 1;
@@ -408,7 +408,7 @@ public class PipesClient implements Closeable {
             }
             if (bos.size() > 0) {
                 LOG.warn("pipesClientId={}: From forked process before start 
byte: {}",
-                        pipesClientId, new String(bos.toByteArray(), 
StandardCharsets.UTF_8));
+                        pipesClientId, bos.toString(StandardCharsets.UTF_8));
             }
             return 1;
         });
@@ -428,7 +428,7 @@ public class PipesClient implements Closeable {
             LOG.error("pipesClientId={} didn't receive ready byte from server 
within " +
                             "StartupTimeoutMillis {}; ms elapsed {}; did read 
>{}<",
                     pipesClientId, pipesConfig.getStartupTimeoutMillis(),
-                    elapsed, new String(bos.toByteArray(), 
StandardCharsets.UTF_8));
+                    elapsed, bos.toString(StandardCharsets.UTF_8));
             destroyForcibly();
             throw e;
         } finally {
@@ -436,8 +436,8 @@ public class PipesClient implements Closeable {
         }
     }
 
-    private static String getMsg(String msg, ByteArrayOutputStream bos) {
-        String readSoFar = new String(bos.toByteArray(), 
StandardCharsets.UTF_8);
+    private static String getMsg(String msg, 
UnsynchronizedByteArrayOutputStream bos) {
+        String readSoFar = bos.toString(StandardCharsets.UTF_8);
         if (StringUtils.isBlank(readSoFar)) {
             return msg;
         } else {
diff --git a/tika-core/src/main/java/org/apache/tika/pipes/PipesServer.java 
b/tika-core/src/main/java/org/apache/tika/pipes/PipesServer.java
index 481f1d2cd..d0d85dd83 100644
--- a/tika-core/src/main/java/org/apache/tika/pipes/PipesServer.java
+++ b/tika-core/src/main/java/org/apache/tika/pipes/PipesServer.java
@@ -16,8 +16,6 @@
  */
 package org.apache.tika.pipes;
 
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
 import java.io.DataInputStream;
 import java.io.DataOutputStream;
 import java.io.IOException;
@@ -31,6 +29,8 @@ import java.nio.file.Paths;
 import java.util.Collections;
 import java.util.List;
 
+import org.apache.commons.io.input.UnsynchronizedByteArrayInputStream;
+import org.apache.commons.io.output.UnsynchronizedByteArrayOutputStream;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.xml.sax.ContentHandler;
@@ -159,7 +159,7 @@ public class PipesServer implements Runnable {
             PipesServer server =
                     new PipesServer(tikaConfig, System.in, System.out, 
maxForEmitBatchBytes,
                             serverParseTimeoutMillis, serverWaitTimeoutMillis);
-            System.setIn(new ByteArrayInputStream(new byte[0]));
+            System.setIn(new UnsynchronizedByteArrayInputStream(new byte[0]));
             System.setOut(System.err);
             Thread watchdog = new Thread(server, "Tika Watchdog");
             watchdog.setDaemon(true);
@@ -581,7 +581,7 @@ public class PipesServer implements Runnable {
             byte[] bytes = new byte[length];
             input.readFully(bytes);
             try (ObjectInputStream objectInputStream = new ObjectInputStream(
-                    new ByteArrayInputStream(bytes))) {
+                    new UnsynchronizedByteArrayInputStream(bytes))) {
                 return (FetchEmitTuple) objectInputStream.readObject();
             }
         } catch (IOException e) {
@@ -607,7 +607,7 @@ public class PipesServer implements Runnable {
 
     private void write(EmitData emitData) {
         try {
-            ByteArrayOutputStream bos = new ByteArrayOutputStream();
+            UnsynchronizedByteArrayOutputStream bos = new 
UnsynchronizedByteArrayOutputStream();
             try (ObjectOutputStream objectOutputStream = new 
ObjectOutputStream(bos)) {
                 objectOutputStream.writeObject(emitData);
             }
diff --git 
a/tika-core/src/main/java/org/apache/tika/utils/RereadableInputStream.java 
b/tika-core/src/main/java/org/apache/tika/utils/RereadableInputStream.java
index b611f038a..db38977b3 100644
--- a/tika-core/src/main/java/org/apache/tika/utils/RereadableInputStream.java
+++ b/tika-core/src/main/java/org/apache/tika/utils/RereadableInputStream.java
@@ -18,7 +18,6 @@ package org.apache.tika.utils;
 
 import java.io.BufferedInputStream;
 import java.io.BufferedOutputStream;
-import java.io.ByteArrayInputStream;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
@@ -27,6 +26,7 @@ import java.io.InputStream;
 import java.io.OutputStream;
 import java.nio.file.Files;
 
+import org.apache.commons.io.input.UnsynchronizedByteArrayInputStream;
 
 /**
  * Wraps an input stream, reading it only once, but making it available
@@ -257,7 +257,7 @@ public class RereadableInputStream extends InputStream {
             // If we have a buffer, then we'll read from it
             if (byteBuffer != null) {
                 readingFromBuffer = true;
-                inputStream = new ByteArrayInputStream(byteBuffer, 0, 
bufferHighWaterMark);
+                inputStream = new 
UnsynchronizedByteArrayInputStream(byteBuffer, 0, bufferHighWaterMark);
             } else {
                 // No buffer, which means we've switched to a file
                 inputStream = new BufferedInputStream(new 
FileInputStream(storeFile));
diff --git a/tika-core/src/main/java/org/apache/tika/utils/XMLReaderUtils.java 
b/tika-core/src/main/java/org/apache/tika/utils/XMLReaderUtils.java
index babd7fc32..9db9d291a 100644
--- a/tika-core/src/main/java/org/apache/tika/utils/XMLReaderUtils.java
+++ b/tika-core/src/main/java/org/apache/tika/utils/XMLReaderUtils.java
@@ -19,6 +19,7 @@ package org.apache.tika.utils;
 
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.Reader;
 import java.io.Serializable;
 import java.io.StringReader;
 import java.lang.reflect.Method;
@@ -400,6 +401,36 @@ public class XMLReaderUtils implements Serializable {
         }
     }
 
+    /**
+     * This checks context for a user specified {@link DocumentBuilder}.
+     * If one is not found, this reuses a DocumentBuilder from the pool.
+     *
+     * @param reader  reader (character stream) to parse
+     * @param context context to use
+     * @return a document
+     * @throws TikaException
+     * @throws IOException
+     * @throws SAXException
+     * @since Apache Tika 2.5
+     */
+    public static Document buildDOM(Reader reader, ParseContext context)
+            throws TikaException, IOException, SAXException {
+        DocumentBuilder builder = context.get(DocumentBuilder.class);
+        PoolDOMBuilder poolBuilder = null;
+        if (builder == null) {
+            poolBuilder = acquireDOMBuilder();
+            builder = poolBuilder.getDocumentBuilder();
+        }
+
+        try {
+            return builder.parse(new InputSource(reader));
+        } finally {
+            if (poolBuilder != null) {
+                releaseDOMBuilder(poolBuilder);
+            }
+        }
+    }
+
     /**
      * Builds a Document with a DocumentBuilder from the pool
      *
@@ -487,6 +518,38 @@ public class XMLReaderUtils implements Serializable {
         }
     }
 
+    /**
+     * This checks context for a user specified {@link SAXParser}.
+     * If one is not found, this reuses a SAXParser from the pool.
+     *
+     * @param reader         reader (character stream) to parse
+     * @param contentHandler handler to use; this wraps a {@link 
OfflineContentHandler}
+     *                       to the content handler as an extra layer of 
defense against
+     *                       external entity vulnerabilities
+     * @param context        context to use
+     * @return
+     * @throws TikaException
+     * @throws IOException
+     * @throws SAXException
+     * @since Apache Tika 2.5
+     */
+    public static void parseSAX(Reader reader, ContentHandler contentHandler, 
ParseContext context)
+            throws TikaException, IOException, SAXException {
+        SAXParser saxParser = context.get(SAXParser.class);
+        PoolSAXParser poolSAXParser = null;
+        if (saxParser == null) {
+            poolSAXParser = acquireSAXParser();
+            saxParser = poolSAXParser.getSAXParser();
+        }
+        try {
+            saxParser.parse(new InputSource(reader), new 
OfflineContentHandler(contentHandler));
+        } finally {
+            if (poolSAXParser != null) {
+                releaseParser(poolSAXParser);
+            }
+        }
+    }
+
     /**
      * Acquire a SAXParser from the pool.  Make sure to
      * {@link #releaseDOMBuilder(PoolDOMBuilder)} in
diff --git 
a/tika-eval/tika-eval-core/src/main/java/org/apache/tika/eval/core/util/ContentTagParser.java
 
b/tika-eval/tika-eval-core/src/main/java/org/apache/tika/eval/core/util/ContentTagParser.java
index 23afe29f5..1e3511d63 100644
--- 
a/tika-eval/tika-eval-core/src/main/java/org/apache/tika/eval/core/util/ContentTagParser.java
+++ 
b/tika-eval/tika-eval-core/src/main/java/org/apache/tika/eval/core/util/ContentTagParser.java
@@ -17,10 +17,8 @@
 
 package org.apache.tika.eval.core.util;
 
-import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.StringReader;
-import java.nio.charset.StandardCharsets;
 import java.util.HashMap;
 import java.util.Locale;
 import java.util.Map;
@@ -45,7 +43,7 @@ public class ContentTagParser {
         Map<String, Integer> tags = new HashMap<>();
         XHTMLContentTagHandler xhtmlContentTagHandler =
                 new XHTMLContentTagHandler(uppercaseTagsOfInterest, tags);
-        XMLReaderUtils.parseSAX(new 
ByteArrayInputStream(html.getBytes(StandardCharsets.UTF_8)),
+        XMLReaderUtils.parseSAX(new StringReader(html),
                 xhtmlContentTagHandler, EMPTY_PARSE_CONTEXT);
         return new ContentTags(xhtmlContentTagHandler.toString(), tags);
     }
diff --git 
a/tika-fuzzing/src/main/java/org/apache/tika/fuzzing/pdf/EvilCOSWriter.java 
b/tika-fuzzing/src/main/java/org/apache/tika/fuzzing/pdf/EvilCOSWriter.java
index 4575690c6..558905bac 100644
--- a/tika-fuzzing/src/main/java/org/apache/tika/fuzzing/pdf/EvilCOSWriter.java
+++ b/tika-fuzzing/src/main/java/org/apache/tika/fuzzing/pdf/EvilCOSWriter.java
@@ -46,6 +46,7 @@ import java.util.Map;
 import java.util.Random;
 import java.util.Set;
 
+import org.apache.commons.io.output.UnsynchronizedByteArrayOutputStream;
 import org.apache.pdfbox.cos.COSArray;
 import org.apache.pdfbox.cos.COSBase;
 import org.apache.pdfbox.cos.COSBoolean;
@@ -873,7 +874,7 @@ public class EvilCOSWriter implements ICOSVisitor, 
Closeable {
         // write existing PDF
         IOUtils.copy(new RandomAccessInputStream(incrementalInput), 
incrementalOutput);
         // write the actual incremental update
-        incrementalOutput.write(((ByteArrayOutputStream) 
output).toByteArray());
+        incrementalOutput.write(getBytes(output));
     }
 
     private void doWriteSignature() throws IOException {
@@ -899,9 +900,8 @@ public class EvilCOSWriter implements ICOSVisitor, 
Closeable {
         }
 
         // copy the new incremental data into a buffer (e.g. signature dict, 
trailer)
-        ByteArrayOutputStream byteOut = (ByteArrayOutputStream) output;
-        byteOut.flush();
-        incrementPart = byteOut.toByteArray();
+        output.flush();
+        incrementPart = getBytes(output);
 
         // overwrite the ByteRange in the buffer
         byte[] byteRangeBytes = 
byteRange.getBytes(StandardCharsets.ISO_8859_1);
@@ -1474,4 +1474,13 @@ public class EvilCOSWriter implements ICOSVisitor, 
Closeable {
         COSDocument cosDoc = fdfDocument.getDocument();
         cosDoc.accept(this);
     }
+
+    private byte[] getBytes(OutputStream stream) throws IOException {
+        if (stream instanceof ByteArrayOutputStream) {
+            return ((ByteArrayOutputStream) stream).toByteArray();
+        } else if (stream instanceof UnsynchronizedByteArrayOutputStream) {
+            return ((UnsynchronizedByteArrayOutputStream) 
stream).toByteArray();
+        }
+        throw new IOException("OutputStream " + stream.getClass().getName() + 
" is not supported");
+    }
 }
diff --git 
a/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/main/java/org/apache/tika/parser/gdal/GDALParser.java
 
b/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/main/java/org/apache/tika/parser/gdal/GDALParser.java
index 1ae76c832..4fc9c2d66 100644
--- 
a/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/main/java/org/apache/tika/parser/gdal/GDALParser.java
+++ 
b/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/main/java/org/apache/tika/parser/gdal/GDALParser.java
@@ -22,11 +22,11 @@ package org.apache.tika.parser.gdal;
 import static java.nio.charset.StandardCharsets.UTF_8;
 import static org.apache.tika.parser.external.ExternalParser.INPUT_FILE_TOKEN;
 
-import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.Reader;
+import java.io.StringReader;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
@@ -334,8 +334,7 @@ public class GDALParser extends AbstractParser {
     private void processOutput(ContentHandler handler, Metadata metadata, 
String output)
             throws SAXException, IOException {
         XHTMLContentHandler xhtml = new XHTMLContentHandler(handler, metadata);
-        InputStream stream = new ByteArrayInputStream(output.getBytes(UTF_8));
-        try (Reader reader = new InputStreamReader(stream, UTF_8)) {
+        try (Reader reader = new StringReader(output)) {
             xhtml.startDocument();
             xhtml.startElement("p");
             char[] buffer = new char[1024];
diff --git 
a/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/main/java/org/apache/tika/parser/hdf/HDFParser.java
 
b/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/main/java/org/apache/tika/parser/hdf/HDFParser.java
index 22ce045ed..4102598f4 100644
--- 
a/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/main/java/org/apache/tika/parser/hdf/HDFParser.java
+++ 
b/tika-parsers/tika-parsers-extended/tika-parser-scientific-module/src/main/java/org/apache/tika/parser/hdf/HDFParser.java
@@ -19,13 +19,13 @@ package org.apache.tika.parser.hdf;
 
 //JDK imports
 
-import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.Collections;
 import java.util.Set;
 
 import org.apache.commons.io.IOUtils;
+import org.apache.commons.io.output.UnsynchronizedByteArrayOutputStream;
 import org.xml.sax.ContentHandler;
 import org.xml.sax.SAXException;
 import ucar.nc2.Attribute;
@@ -79,7 +79,7 @@ public class HDFParser extends AbstractParser {
      */
     public void parse(InputStream stream, ContentHandler handler, Metadata 
metadata,
                       ParseContext context) throws IOException, SAXException, 
TikaException {
-        ByteArrayOutputStream os = new ByteArrayOutputStream();
+        UnsynchronizedByteArrayOutputStream os = new 
UnsynchronizedByteArrayOutputStream();
         IOUtils.copy(stream, os);
 
         String name = metadata.get(TikaCoreProperties.RESOURCE_NAME_KEY);
diff --git 
a/tika-parsers/tika-parsers-ml/tika-parser-advancedmedia-module/src/main/java/org/apache/tika/parser/captioning/tf/TensorflowRESTCaptioner.java
 
b/tika-parsers/tika-parsers-ml/tika-parser-advancedmedia-module/src/main/java/org/apache/tika/parser/captioning/tf/TensorflowRESTCaptioner.java
index 55a721ef6..f36576d44 100644
--- 
a/tika-parsers/tika-parsers-ml/tika-parser-advancedmedia-module/src/main/java/org/apache/tika/parser/captioning/tf/TensorflowRESTCaptioner.java
+++ 
b/tika-parsers/tika-parsers-ml/tika-parser-advancedmedia-module/src/main/java/org/apache/tika/parser/captioning/tf/TensorflowRESTCaptioner.java
@@ -17,7 +17,6 @@
 
 package org.apache.tika.parser.captioning.tf;
 
-import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.URI;
@@ -32,6 +31,7 @@ import java.util.Map;
 import java.util.Set;
 
 import org.apache.commons.io.IOUtils;
+import org.apache.commons.io.output.UnsynchronizedByteArrayOutputStream;
 import org.apache.http.HttpResponse;
 import org.apache.http.client.methods.HttpGet;
 import org.apache.http.client.methods.HttpPost;
@@ -138,7 +138,7 @@ public class TensorflowRESTCaptioner implements 
ObjectRecogniser {
 
             HttpPost request = new HttpPost(getApiUri(metadata));
 
-            try (ByteArrayOutputStream byteStream = new 
ByteArrayOutputStream()) {
+            try (UnsynchronizedByteArrayOutputStream byteStream = new 
UnsynchronizedByteArrayOutputStream()) {
                 //TODO: convert this to stream, this might cause OOM issue
                 // InputStreamEntity is not working
                 // request.setEntity(new InputStreamEntity(stream, -1));
diff --git 
a/tika-parsers/tika-parsers-ml/tika-parser-advancedmedia-module/src/main/java/org/apache/tika/parser/pot/PooledTimeSeriesParser.java
 
b/tika-parsers/tika-parsers-ml/tika-parser-advancedmedia-module/src/main/java/org/apache/tika/parser/pot/PooledTimeSeriesParser.java
index c48d9a123..d86959368 100644
--- 
a/tika-parsers/tika-parsers-ml/tika-parser-advancedmedia-module/src/main/java/org/apache/tika/parser/pot/PooledTimeSeriesParser.java
+++ 
b/tika-parsers/tika-parsers-ml/tika-parser-advancedmedia-module/src/main/java/org/apache/tika/parser/pot/PooledTimeSeriesParser.java
@@ -20,7 +20,6 @@ package org.apache.tika.parser.pot;
 import static java.nio.charset.StandardCharsets.UTF_8;
 
 import java.io.BufferedReader;
-import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
@@ -37,6 +36,7 @@ import org.apache.commons.exec.DefaultExecutor;
 import org.apache.commons.exec.ExecuteWatchdog;
 import org.apache.commons.exec.PumpStreamHandler;
 import org.apache.commons.exec.environment.EnvironmentUtils;
+import org.apache.commons.io.output.UnsynchronizedByteArrayOutputStream;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.xml.sax.ContentHandler;
@@ -154,22 +154,22 @@ public class PooledTimeSeriesParser extends 
AbstractParser {
         }
     }
 
-    private String computePoT(File input) throws IOException, TikaException {
+    private String computePoT(File input) throws IOException {
 
         CommandLine cmdLine = new CommandLine("pooled-time-series");
-        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
-        cmdLine.addArgument("-f");
-        cmdLine.addArgument(input.getAbsolutePath());
-        LOG.trace("Executing: {}", cmdLine);
-        DefaultExecutor exec = new DefaultExecutor();
-        exec.setExitValue(0);
-        ExecuteWatchdog watchdog = new ExecuteWatchdog(60000);
-        exec.setWatchdog(watchdog);
-        PumpStreamHandler streamHandler = new PumpStreamHandler(outputStream);
-        exec.setStreamHandler(streamHandler);
-        int exitValue = exec.execute(cmdLine, 
EnvironmentUtils.getProcEnvironment());
-        return outputStream.toString("UTF-8");
-
+        try (UnsynchronizedByteArrayOutputStream outputStream = new 
UnsynchronizedByteArrayOutputStream()) {
+            cmdLine.addArgument("-f");
+            cmdLine.addArgument(input.getAbsolutePath());
+            LOG.trace("Executing: {}", cmdLine);
+            DefaultExecutor exec = new DefaultExecutor();
+            exec.setExitValue(0);
+            ExecuteWatchdog watchdog = new ExecuteWatchdog(60000);
+            exec.setWatchdog(watchdog);
+            PumpStreamHandler streamHandler = new 
PumpStreamHandler(outputStream);
+            exec.setStreamHandler(streamHandler);
+            int exitValue = exec.execute(cmdLine, 
EnvironmentUtils.getProcEnvironment());
+            return outputStream.toString(UTF_8);
+        }
     }
 
     /**
diff --git 
a/tika-parsers/tika-parsers-ml/tika-parser-advancedmedia-module/src/main/java/org/apache/tika/parser/recognition/tf/TensorflowRESTRecogniser.java
 
b/tika-parsers/tika-parsers-ml/tika-parser-advancedmedia-module/src/main/java/org/apache/tika/parser/recognition/tf/TensorflowRESTRecogniser.java
index 3983f27a1..d7734ca06 100644
--- 
a/tika-parsers/tika-parsers-ml/tika-parser-advancedmedia-module/src/main/java/org/apache/tika/parser/recognition/tf/TensorflowRESTRecogniser.java
+++ 
b/tika-parsers/tika-parsers-ml/tika-parser-advancedmedia-module/src/main/java/org/apache/tika/parser/recognition/tf/TensorflowRESTRecogniser.java
@@ -17,7 +17,6 @@
 
 package org.apache.tika.parser.recognition.tf;
 
-import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.URI;
@@ -34,6 +33,7 @@ import java.util.Set;
 import com.github.openjson.JSONArray;
 import com.github.openjson.JSONObject;
 import org.apache.commons.io.IOUtils;
+import org.apache.commons.io.output.UnsynchronizedByteArrayOutputStream;
 import org.apache.http.HttpResponse;
 import org.apache.http.client.methods.HttpGet;
 import org.apache.http.client.methods.HttpPost;
@@ -139,7 +139,7 @@ public class TensorflowRESTRecogniser implements 
ObjectRecogniser {
 
             HttpPost request = new HttpPost(getApiUri(metadata));
 
-            try (ByteArrayOutputStream byteStream = new 
ByteArrayOutputStream()) {
+            try (UnsynchronizedByteArrayOutputStream byteStream = new 
UnsynchronizedByteArrayOutputStream()) {
                 //TODO: convert this to stream, this might cause OOM issue
                 // InputStreamEntity is not working
                 // request.setEntity(new InputStreamEntity(stream, -1));
diff --git 
a/tika-parsers/tika-parsers-ml/tika-parser-nlp-module/src/main/java/org/apache/tika/parser/journal/TEIDOMParser.java
 
b/tika-parsers/tika-parsers-ml/tika-parser-nlp-module/src/main/java/org/apache/tika/parser/journal/TEIDOMParser.java
index 222767bfb..6ca9a35d2 100644
--- 
a/tika-parsers/tika-parsers-ml/tika-parser-nlp-module/src/main/java/org/apache/tika/parser/journal/TEIDOMParser.java
+++ 
b/tika-parsers/tika-parsers-ml/tika-parser-nlp-module/src/main/java/org/apache/tika/parser/journal/TEIDOMParser.java
@@ -17,9 +17,8 @@
 
 package org.apache.tika.parser.journal;
 
-import java.io.ByteArrayInputStream;
 import java.io.IOException;
-import java.nio.charset.StandardCharsets;
+import java.io.StringReader;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Objects;
@@ -80,8 +79,7 @@ public class TEIDOMParser {
             throws TikaException, SAXException, IOException {
 
         Document root = XMLReaderUtils
-                .buildDOM(new 
ByteArrayInputStream(source.getBytes(StandardCharsets.UTF_8)),
-                        parseContext);
+                .buildDOM(new StringReader(source), parseContext);
 
         Metadata metadata = new Metadata();
         createGrobidMetadata(source, root.getDocumentElement(), metadata);
diff --git 
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/video/FLVParser.java
 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/video/FLVParser.java
index cbacdfbb4..49f3537e3 100644
--- 
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/video/FLVParser.java
+++ 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/video/FLVParser.java
@@ -18,7 +18,6 @@ package org.apache.tika.parser.video;
 
 import static java.nio.charset.StandardCharsets.UTF_8;
 
-import java.io.ByteArrayInputStream;
 import java.io.DataInputStream;
 import java.io.IOException;
 import java.io.InputStream;
@@ -30,6 +29,7 @@ import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
 
+import org.apache.commons.io.input.UnsynchronizedByteArrayInputStream;
 import org.xml.sax.ContentHandler;
 import org.xml.sax.SAXException;
 
@@ -224,25 +224,26 @@ public class FLVParser extends AbstractParser {
                     }
                 }
 
-                ByteArrayInputStream is = new ByteArrayInputStream(metaBytes);
+                try (
+                        UnsynchronizedByteArrayInputStream is = new 
UnsynchronizedByteArrayInputStream(metaBytes);
+                        DataInputStream dis = new DataInputStream(is);
+                ) {
+                    Object data = null;
 
-                DataInputStream dis = new DataInputStream(is);
-
-                Object data = null;
-
-                for (int i = 0; i < 2; i++) {
-                    data = readAMFData(dis, -1);
-                }
+                    for (int i = 0; i < 2; i++) {
+                        data = readAMFData(dis, -1);
+                    }
 
-                if (data instanceof Map) {
-                    // TODO if there are multiple metadata values with same 
key (in
-                    // separate AMF blocks, we currently loose previous values)
-                    Map<String, Object> extractedMetadata = (Map<String, 
Object>) data;
-                    for (Entry<String, Object> entry : 
extractedMetadata.entrySet()) {
-                        if (entry.getValue() == null) {
-                            continue;
+                    if (data instanceof Map) {
+                        // TODO if there are multiple metadata values with 
same key (in
+                        // separate AMF blocks, we currently loose previous 
values)
+                        Map<String, Object> extractedMetadata = (Map<String, 
Object>) data;
+                        for (Entry<String, Object> entry : 
extractedMetadata.entrySet()) {
+                            if (entry.getValue() == null) {
+                                continue;
+                            }
+                            metadata.set(entry.getKey(), 
entry.getValue().toString());
                         }
-                        metadata.set(entry.getKey(), 
entry.getValue().toString());
                     }
                 }
 
diff --git 
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-html-module/src/main/java/org/apache/tika/parser/html/DataURIScheme.java
 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-html-module/src/main/java/org/apache/tika/parser/html/DataURIScheme.java
index 0fac0181f..0533b4767 100644
--- 
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-html-module/src/main/java/org/apache/tika/parser/html/DataURIScheme.java
+++ 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-html-module/src/main/java/org/apache/tika/parser/html/DataURIScheme.java
@@ -17,11 +17,12 @@
 
 package org.apache.tika.parser.html;
 
-import java.io.ByteArrayInputStream;
 import java.io.InputStream;
 import java.util.Arrays;
 import java.util.Objects;
 
+import org.apache.commons.io.input.UnsynchronizedByteArrayInputStream;
+
 import org.apache.tika.mime.MediaType;
 
 public class DataURIScheme {
@@ -38,7 +39,7 @@ public class DataURIScheme {
     }
 
     public InputStream getInputStream() {
-        return new ByteArrayInputStream(data);
+        return new UnsynchronizedByteArrayInputStream(data);
     }
 
     /**
diff --git 
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-html-module/src/main/java/org/apache/tika/parser/html/HtmlHandler.java
 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-html-module/src/main/java/org/apache/tika/parser/html/HtmlHandler.java
index 4a208d89d..9b79ef75d 100644
--- 
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-html-module/src/main/java/org/apache/tika/parser/html/HtmlHandler.java
+++ 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-html-module/src/main/java/org/apache/tika/parser/html/HtmlHandler.java
@@ -16,7 +16,6 @@
  */
 package org.apache.tika.parser.html;
 
-import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.MalformedURLException;
@@ -30,6 +29,7 @@ import java.util.Set;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
+import org.apache.commons.io.input.UnsynchronizedByteArrayInputStream;
 import org.xml.sax.Attributes;
 import org.xml.sax.ContentHandler;
 import org.xml.sax.SAXException;
@@ -364,7 +364,7 @@ class HtmlHandler extends TextContentHandler {
             }
         }
 
-        try (InputStream stream = new ByteArrayInputStream(
+        try (InputStream stream = new UnsynchronizedByteArrayInputStream(
                 script.toString().getBytes(StandardCharsets.UTF_8))) {
             embeddedDocumentExtractor.parseEmbedded(stream, xhtml, m, true);
         } catch (IOException e) {
diff --git 
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-image-module/src/main/java/org/apache/tika/parser/image/ImageMetadataExtractor.java
 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-image-module/src/main/java/org/apache/tika/parser/image/ImageMetadataExtractor.java
index 3870ae939..ce1b503f2 100644
--- 
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-image-module/src/main/java/org/apache/tika/parser/image/ImageMetadataExtractor.java
+++ 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-image-module/src/main/java/org/apache/tika/parser/image/ImageMetadataExtractor.java
@@ -16,7 +16,6 @@
  */
 package org.apache.tika.parser.image;
 
-import java.io.ByteArrayInputStream;
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
@@ -54,6 +53,7 @@ import com.drew.metadata.iptc.IptcDirectory;
 import com.drew.metadata.jpeg.JpegCommentDirectory;
 import com.drew.metadata.jpeg.JpegDirectory;
 import org.apache.commons.io.IOUtils;
+import org.apache.commons.io.input.UnsynchronizedByteArrayInputStream;
 import org.apache.jempbox.xmp.XMPMetadata;
 import org.w3c.dom.Document;
 import org.xml.sax.SAXException;
@@ -186,7 +186,7 @@ public class ImageMetadataExtractor {
 
     public void parseRawXMP(byte[] xmpData) throws IOException, SAXException, 
TikaException {
         XMPMetadata xmp = null;
-        try (InputStream decoded = new ByteArrayInputStream(xmpData)) {
+        try (InputStream decoded = new 
UnsynchronizedByteArrayInputStream(xmpData)) {
             Document dom = XMLReaderUtils.buildDOM(decoded, 
EMPTY_PARSE_CONTEXT);
             if (dom != null) {
                 xmp = new XMPMetadata(dom);
diff --git 
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-image-module/src/main/java/org/apache/tika/parser/image/PSDParser.java
 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-image-module/src/main/java/org/apache/tika/parser/image/PSDParser.java
index 957a26e2c..a342f303d 100644
--- 
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-image-module/src/main/java/org/apache/tika/parser/image/PSDParser.java
+++ 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-image-module/src/main/java/org/apache/tika/parser/image/PSDParser.java
@@ -18,7 +18,6 @@ package org.apache.tika.parser.image;
 
 import static java.nio.charset.StandardCharsets.US_ASCII;
 
-import java.io.ByteArrayInputStream;
 import java.io.EOFException;
 import java.io.IOException;
 import java.io.InputStream;
@@ -27,6 +26,7 @@ import java.util.HashSet;
 import java.util.Set;
 
 import org.apache.commons.io.IOUtils;
+import org.apache.commons.io.input.UnsynchronizedByteArrayInputStream;
 import org.xml.sax.ContentHandler;
 import org.xml.sax.SAXException;
 
@@ -145,7 +145,7 @@ public class PSDParser extends AbstractParser {
                 //if there are multiple xmps in a file, this will
                 //overwrite the data from the earlier xmp
                 JempboxExtractor ex = new JempboxExtractor(metadata);
-                ex.parse(new ByteArrayInputStream(rb.data));
+                ex.parse(new UnsynchronizedByteArrayInputStream(rb.data));
             }
             blocks++;
         }
diff --git 
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-jdbc-commons/src/main/java/org/apache/tika/parser/jdbc/JDBCTableReader.java
 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-jdbc-commons/src/main/java/org/apache/tika/parser/jdbc/JDBCTableReader.java
index 6291a2406..3944df3ef 100644
--- 
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-jdbc-commons/src/main/java/org/apache/tika/parser/jdbc/JDBCTableReader.java
+++ 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-jdbc-commons/src/main/java/org/apache/tika/parser/jdbc/JDBCTableReader.java
@@ -18,7 +18,6 @@ package org.apache.tika.parser.jdbc;
 
 import static java.nio.charset.StandardCharsets.UTF_8;
 
-import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.sql.Blob;
 import java.sql.Clob;
@@ -33,6 +32,7 @@ import java.util.List;
 
 import org.apache.commons.io.FilenameUtils;
 import org.apache.commons.io.IOUtils;
+import org.apache.commons.io.input.UnsynchronizedByteArrayInputStream;
 import org.xml.sax.Attributes;
 import org.xml.sax.ContentHandler;
 import org.xml.sax.SAXException;
@@ -201,7 +201,7 @@ public class JDBCTableReader {
         String s = clob.getSubString(0, readSize);
         if (embeddedDocumentUtil.shouldParseEmbedded(m)) {
             embeddedDocumentUtil
-                    .parseEmbedded(new 
ByteArrayInputStream(s.getBytes(UTF_8)), handler, m, true);
+                    .parseEmbedded(new 
UnsynchronizedByteArrayInputStream(s.getBytes(UTF_8)), handler, m, true);
         }
     }
 
diff --git 
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-mail-module/src/main/java/org/apache/tika/parser/mail/MailContentHandler.java
 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-mail-module/src/main/java/org/apache/tika/parser/mail/MailContentHandler.java
index e4f369795..2a5e76d7d 100644
--- 
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-mail-module/src/main/java/org/apache/tika/parser/mail/MailContentHandler.java
+++ 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-mail-module/src/main/java/org/apache/tika/parser/mail/MailContentHandler.java
@@ -19,8 +19,6 @@ package org.apache.tika.parser.mail;
 import static org.apache.tika.utils.DateUtils.MIDDAY;
 import static org.apache.tika.utils.DateUtils.UTC;
 
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.text.DateFormat;
@@ -39,6 +37,8 @@ import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
 import org.apache.commons.io.IOUtils;
+import org.apache.commons.io.input.UnsynchronizedByteArrayInputStream;
+import org.apache.commons.io.output.UnsynchronizedByteArrayOutputStream;
 import org.apache.james.mime4j.MimeException;
 import org.apache.james.mime4j.codec.DecodeMonitor;
 import org.apache.james.mime4j.codec.DecoderUtil;
@@ -231,7 +231,7 @@ class MailContentHandler implements ContentHandler {
         //if we're in a multipart/alternative or any one of its children
         //add the bodypart to the latest that was added
         if (!extractAllAlternatives && alternativePartBuffer.size() > 0) {
-            ByteArrayOutputStream bos = new ByteArrayOutputStream();
+            UnsynchronizedByteArrayOutputStream bos = new 
UnsynchronizedByteArrayOutputStream();
             IOUtils.copy(is, bos);
             alternativePartBuffer.peek().children.add(new BodyContents(submd, 
bos.toByteArray()));
         } else if (!extractAllAlternatives && parts.size() < 2) {
@@ -239,11 +239,11 @@ class MailContentHandler implements ContentHandler {
             //and you're not in an alternative part block
             //and you're text/html, put that in the body of the email
             //otherwise treat as a regular attachment
-            ByteArrayOutputStream bos = new ByteArrayOutputStream();
+            UnsynchronizedByteArrayOutputStream bos = new 
UnsynchronizedByteArrayOutputStream();
             IOUtils.copy(is, bos);
-            byte[] bytes = bos.toByteArray();
+            final byte[] bytes = bos.toByteArray();
             if (detectTextOrHtml(submd, bytes)) {
-                handleInlineBodyPart(new BodyContents(submd, 
bos.toByteArray()));
+                handleInlineBodyPart(new BodyContents(submd, bytes));
             } else {
                 //else handle as you would any other embedded content
                 try (TikaInputStream tis = TikaInputStream.get(bytes)) {
@@ -601,7 +601,7 @@ class MailContentHandler implements ContentHandler {
                     
inlineMetadata.set(TikaCoreProperties.CONTENT_TYPE_PARSER_OVERRIDE,
                             MediaType.TEXT_PLAIN.toString());
                 }
-                parser.parse(new ByteArrayInputStream(part.bytes),
+                parser.parse(new 
UnsynchronizedByteArrayInputStream(part.bytes),
                         new EmbeddedContentHandler(new 
BodyContentHandler(handler)), inlineMetadata,
                         parseContext);
             } catch (SAXException | TikaException e) {
diff --git 
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-mail-module/src/main/java/org/apache/tika/parser/mbox/MboxParser.java
 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-mail-module/src/main/java/org/apache/tika/parser/mbox/MboxParser.java
index b4e727423..a09a3fcfa 100644
--- 
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-mail-module/src/main/java/org/apache/tika/parser/mbox/MboxParser.java
+++ 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-mail-module/src/main/java/org/apache/tika/parser/mbox/MboxParser.java
@@ -19,8 +19,6 @@ package org.apache.tika.parser.mbox;
 import static org.apache.tika.parser.mailcommons.MailDateParser.parseDate;
 
 import java.io.BufferedReader;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
@@ -36,6 +34,7 @@ import java.util.Set;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
+import org.apache.commons.io.output.UnsynchronizedByteArrayOutputStream;
 import org.xml.sax.ContentHandler;
 import org.xml.sax.SAXException;
 
@@ -110,7 +109,7 @@ public class MboxParser extends AbstractParser {
                     if (curLine == null) {
                         break;
                     }
-                    ByteArrayOutputStream message = new 
ByteArrayOutputStream(100000);
+                    UnsynchronizedByteArrayOutputStream message = new 
UnsynchronizedByteArrayOutputStream(100000);
                     do {
                         if (curLine.startsWith(" ") || 
curLine.startsWith("\t")) {
                             String latestLine = multiline.poll();
@@ -130,8 +129,7 @@ public class MboxParser extends AbstractParser {
                         saveHeaderInMetadata(mailMetadata, item);
                     }
 
-                    ByteArrayInputStream messageStream =
-                            new ByteArrayInputStream(message.toByteArray());
+                    InputStream messageStream = message.toInputStream();
                     message = null;
 
                     if (extractor.shouldParseEmbedded(mailMetadata)) {
diff --git 
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/extractor/microsoft/MSEmbeddedStreamTranslator.java
 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/extractor/microsoft/MSEmbeddedStreamTranslator.java
index 2d51a869e..0a242ee7f 100644
--- 
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/extractor/microsoft/MSEmbeddedStreamTranslator.java
+++ 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/extractor/microsoft/MSEmbeddedStreamTranslator.java
@@ -16,12 +16,12 @@
  */
 package org.apache.tika.extractor.microsoft;
 
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 
 import org.apache.commons.io.IOUtils;
+import org.apache.commons.io.input.UnsynchronizedByteArrayInputStream;
+import org.apache.commons.io.output.UnsynchronizedByteArrayOutputStream;
 import org.apache.poi.poifs.filesystem.DirectoryEntry;
 import org.apache.poi.poifs.filesystem.DocumentEntry;
 import org.apache.poi.poifs.filesystem.DocumentInputStream;
@@ -61,13 +61,13 @@ public class MSEmbeddedStreamTranslator implements 
EmbeddedStreamTranslator {
     public InputStream translate(InputStream inputStream, Metadata metadata) 
throws IOException {
         String contentType = 
metadata.get(org.apache.tika.metadata.HttpHeaders.CONTENT_TYPE);
         if 
("application/vnd.openxmlformats-officedocument.oleObject".equals(contentType)) 
{
-            ByteArrayOutputStream bos = new ByteArrayOutputStream();
+            UnsynchronizedByteArrayOutputStream bos = new 
UnsynchronizedByteArrayOutputStream();
             IOUtils.copy(inputStream, bos);
-            byte[] data = bos.toByteArray();
-            POIFSFileSystem poifs = new POIFSFileSystem(new 
ByteArrayInputStream(data));
+            POIFSFileSystem poifs = new POIFSFileSystem(bos.toInputStream());
             OfficeParser.POIFSDocumentType type = 
OfficeParser.POIFSDocumentType.detectType(poifs);
             String name = metadata.get(TikaCoreProperties.RESOURCE_NAME_KEY);
 
+            byte[] data = bos.toByteArray();
             if (type == OfficeParser.POIFSDocumentType.OLE10_NATIVE) {
                 try {
                     Ole10Native ole = 
Ole10Native.createFromEmbeddedOleObject(poifs);
@@ -82,7 +82,7 @@ public class MSEmbeddedStreamTranslator implements 
EmbeddedStreamTranslator {
                 name += '.' + type.getExtension();
             }
             metadata.set(TikaCoreProperties.RESOURCE_NAME_KEY, name);
-            return new ByteArrayInputStream(data);
+            return new UnsynchronizedByteArrayInputStream(data);
         } else if (inputStream instanceof TikaInputStream) {
             TikaInputStream tin = (TikaInputStream) inputStream;
 
@@ -90,10 +90,10 @@ public class MSEmbeddedStreamTranslator implements 
EmbeddedStreamTranslator {
                     tin.getOpenContainer() instanceof DirectoryEntry) {
                 POIFSFileSystem fs = new POIFSFileSystem();
                 copy((DirectoryEntry) tin.getOpenContainer(), fs.getRoot());
-                ByteArrayOutputStream bos2 = new ByteArrayOutputStream();
-                fs.writeFilesystem(bos2);
-                bos2.close();
-                return new ByteArrayInputStream(bos2.toByteArray());
+                try (UnsynchronizedByteArrayOutputStream bos2 = new 
UnsynchronizedByteArrayOutputStream()) {
+                    fs.writeFilesystem(bos2);
+                    return bos2.toInputStream();
+                }
             }
         }
         return inputStream;
diff --git 
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/JackcessExtractor.java
 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/JackcessExtractor.java
index a224fbca3..44cd6dcda 100644
--- 
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/JackcessExtractor.java
+++ 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/JackcessExtractor.java
@@ -20,7 +20,6 @@ package org.apache.tika.parser.microsoft;
 
 import static java.nio.charset.StandardCharsets.UTF_8;
 
-import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.math.BigDecimal;
@@ -42,6 +41,7 @@ import com.healthmarketscience.jackcess.Table;
 import com.healthmarketscience.jackcess.query.Query;
 import com.healthmarketscience.jackcess.util.OleBlob;
 import org.apache.commons.io.IOUtils;
+import org.apache.commons.io.input.UnsynchronizedByteArrayInputStream;
 import org.apache.poi.poifs.filesystem.POIFSFileSystem;
 import org.xml.sax.SAXException;
 
@@ -222,7 +222,7 @@ class JackcessExtractor extends AbstractPOIFSExtractor {
                 m.set(Metadata.CONTENT_TYPE, "text/html; charset=UTF-8");
                 try {
                     htmlParser
-                            .parse(new 
ByteArrayInputStream(v.getBytes(UTF_8)), h, m, parseContext);
+                            .parse(new 
UnsynchronizedByteArrayInputStream(v.getBytes(UTF_8)), h, m, parseContext);
                     handler.characters(h.toString());
                 } catch (SAXException e) {
                     WriteLimitReachedException.throwIfWriteLimitReached(e);
diff --git 
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/OfficeParser.java
 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/OfficeParser.java
index 280b486bd..0b78fcdab 100644
--- 
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/OfficeParser.java
+++ 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/OfficeParser.java
@@ -16,7 +16,6 @@
  */
 package org.apache.tika.parser.microsoft;
 
-import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.nio.charset.StandardCharsets;
@@ -31,6 +30,7 @@ import java.util.Set;
 
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.io.input.CloseShieldInputStream;
+import org.apache.commons.io.input.UnsynchronizedByteArrayInputStream;
 import org.apache.poi.hdgf.extractor.VisioTextExtractor;
 import org.apache.poi.hpbf.extractor.PublisherTextExtractor;
 import org.apache.poi.poifs.crypt.Decryptor;
@@ -115,7 +115,7 @@ public class OfficeParser extends AbstractOfficeParser {
             if (embeddedDocumentExtractor.shouldParseEmbedded(m)) {
                 embeddedDocumentExtractor.parseEmbedded(
                         //pass in space character so that we don't trigger a 
zero-byte exception
-                        new ByteArrayInputStream(new byte[]{'\u0020'}), xhtml, 
m, true);
+                        new UnsynchronizedByteArrayInputStream(new 
byte[]{'\u0020'}), xhtml, m, true);
             }
             return;
         }
@@ -126,7 +126,7 @@ public class OfficeParser extends AbstractOfficeParser {
             m.set(Metadata.CONTENT_TYPE, "text/x-vbasic");
             if (embeddedDocumentExtractor.shouldParseEmbedded(m)) {
                 embeddedDocumentExtractor.parseEmbedded(
-                        new 
ByteArrayInputStream(e.getValue().getBytes(StandardCharsets.UTF_8)),
+                        new 
UnsynchronizedByteArrayInputStream(e.getValue().getBytes(StandardCharsets.UTF_8)),
                         xhtml, m, true);
             }
         }
diff --git 
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/OutlookExtractor.java
 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/OutlookExtractor.java
index 2f19dec1a..4e9ce90e2 100644
--- 
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/OutlookExtractor.java
+++ 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/OutlookExtractor.java
@@ -18,7 +18,6 @@ package org.apache.tika.parser.microsoft;
 
 import static java.nio.charset.StandardCharsets.UTF_8;
 
-import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.UnsupportedEncodingException;
 import java.nio.charset.Charset;
@@ -36,6 +35,7 @@ import java.util.Map;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
+import org.apache.commons.io.input.UnsynchronizedByteArrayInputStream;
 import org.apache.james.mime4j.codec.DecodeMonitor;
 import org.apache.james.mime4j.codec.DecoderUtil;
 import org.apache.poi.hmef.attribute.MAPIRtfAttribute;
@@ -370,7 +370,7 @@ public class OutlookExtractor extends 
AbstractPOIFSExtractor {
                 if (htmlParser == null) {
                     htmlParser = new HtmlParser();
                 }
-                htmlParser.parse(new ByteArrayInputStream(data),
+                htmlParser.parse(new UnsynchronizedByteArrayInputStream(data),
                         new EmbeddedContentHandler(new 
BodyContentHandler(xhtml)), new Metadata(),
                         parseContext);
                 doneBody = true;
@@ -390,7 +390,7 @@ public class OutlookExtractor extends 
AbstractPOIFSExtractor {
                 if (rtfParser == null) {
                     rtfParser = new RTFParser();
                 }
-                rtfParser.parse(new ByteArrayInputStream(rtf.getData()),
+                rtfParser.parse(new 
UnsynchronizedByteArrayInputStream(rtf.getData()),
                         new EmbeddedContentHandler(new 
BodyContentHandler(xhtml)), new Metadata(),
                         parseContext);
                 doneBody = true;
@@ -650,7 +650,7 @@ public class OutlookExtractor extends 
AbstractPOIFSExtractor {
             if (html != null && html.length() > 0) {
                 Charset charset = null;
                 try {
-                    charset = detector.detect(new 
ByteArrayInputStream(html.getBytes(UTF_8)),
+                    charset = detector.detect(new 
UnsynchronizedByteArrayInputStream(html.getBytes(UTF_8)),
                             EMPTY_METADATA);
                 } catch (IOException e) {
                     //swallow
diff --git 
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/chm/ChmExtractor.java
 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/chm/ChmExtractor.java
index 912d0392a..ba1738b65 100644
--- 
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/chm/ChmExtractor.java
+++ 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/chm/ChmExtractor.java
@@ -18,13 +18,13 @@ package org.apache.tika.parser.microsoft.chm;
 
 import static java.nio.charset.StandardCharsets.UTF_8;
 
-import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.ArrayList;
 import java.util.List;
 
 import org.apache.commons.io.IOUtils;
+import org.apache.commons.io.output.UnsynchronizedByteArrayOutputStream;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -251,7 +251,7 @@ public class ChmExtractor {
      */
     public byte[] extractChmEntry(DirectoryListingEntry directoryListingEntry)
             throws TikaException {
-        ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+        UnsynchronizedByteArrayOutputStream buffer = new 
UnsynchronizedByteArrayOutputStream();
         ChmLzxBlock lzxBlock = null;
         try {
             /* UNCOMPRESSED type is easiest one */
diff --git 
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/chm/ChmParser.java
 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/chm/ChmParser.java
index 9a940a97c..29e719c35 100644
--- 
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/chm/ChmParser.java
+++ 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/chm/ChmParser.java
@@ -16,7 +16,6 @@
  */
 package org.apache.tika.parser.microsoft.chm;
 
-import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.Arrays;
@@ -24,6 +23,7 @@ import java.util.Collections;
 import java.util.HashSet;
 import java.util.Set;
 
+import org.apache.commons.io.input.UnsynchronizedByteArrayInputStream;
 import org.xml.sax.ContentHandler;
 import org.xml.sax.SAXException;
 
@@ -99,7 +99,7 @@ public class ChmParser extends AbstractParser {
         Metadata metadata = new Metadata();
         ContentHandler handler = new EmbeddedContentHandler(new 
BodyContentHandler(xhtml));// -1
         try {
-            stream = new ByteArrayInputStream(byteObject);
+            stream = new UnsynchronizedByteArrayInputStream(byteObject);
             htmlParser.parse(stream, handler, metadata, context);
         } catch (IOException e) {
             // Pushback overflow from tagsoup
diff --git 
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/onenote/OneNoteLegacyDumpStrings.java
 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/onenote/OneNoteLegacyDumpStrings.java
index 9a089b7a2..35e4613ca 100644
--- 
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/onenote/OneNoteLegacyDumpStrings.java
+++ 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/onenote/OneNoteLegacyDumpStrings.java
@@ -16,11 +16,11 @@
  */
 package org.apache.tika.parser.microsoft.onenote;
 
-import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.nio.ByteBuffer;
 import java.nio.charset.StandardCharsets;
 
+import org.apache.commons.io.output.UnsynchronizedByteArrayOutputStream;
 import org.xml.sax.SAXException;
 
 import org.apache.tika.exception.TikaException;
@@ -71,7 +71,7 @@ class OneNoteLegacyDumpStrings {
     private void dumpAscii() throws SAXException, TikaException {
         try {
             oneNoteDirectFileResource.position(0);
-            ByteArrayOutputStream os = new ByteArrayOutputStream();
+            UnsynchronizedByteArrayOutputStream os = new 
UnsynchronizedByteArrayOutputStream();
             long sz = oneNoteDirectFileResource.size();
             long pos;
             while ((pos = oneNoteDirectFileResource.position()) != sz) {
@@ -108,7 +108,7 @@ class OneNoteLegacyDumpStrings {
     private void dumpUtf16LE() throws SAXException, TikaException {
         try {
             oneNoteDirectFileResource.position(0);
-            ByteArrayOutputStream os = new ByteArrayOutputStream();
+            UnsynchronizedByteArrayOutputStream os = new 
UnsynchronizedByteArrayOutputStream();
             long sz = oneNoteDirectFileResource.size();
             long bufSize = BUFFER_SIZE;
             // Make sure the buffer size is a multiple of 2.
@@ -154,8 +154,8 @@ class OneNoteLegacyDumpStrings {
      *
      * @param os Byte array output stream containing the buffer.
      */
-    private void writeIfUseful(ByteArrayOutputStream os) throws SAXException {
-        String str = new String(os.toByteArray(), StandardCharsets.ISO_8859_1);
+    private void writeIfUseful(UnsynchronizedByteArrayOutputStream os) throws 
SAXException {
+        String str = os.toString(StandardCharsets.ISO_8859_1);
         String[] spl = str.split(" ");
         if (spl.length > 1) {
             int numAlpha = 0;
diff --git 
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/ooxml/xwpf/ml2006/BinaryDataHandler.java
 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/ooxml/xwpf/ml2006/BinaryDataHandler.java
index e0898fe00..ad75c096a 100644
--- 
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/ooxml/xwpf/ml2006/BinaryDataHandler.java
+++ 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/ooxml/xwpf/ml2006/BinaryDataHandler.java
@@ -18,11 +18,11 @@
 package org.apache.tika.parser.microsoft.ooxml.xwpf.ml2006;
 
 
-import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 
 import org.apache.commons.codec.binary.Base64;
+import org.apache.commons.io.input.UnsynchronizedByteArrayInputStream;
 import org.xml.sax.Attributes;
 import org.xml.sax.SAXException;
 
@@ -115,6 +115,6 @@ class BinaryDataHandler extends AbstractPartHandler {
 
     private InputStream getInputStream() {
         byte[] bytes = base64.decode(buffer.toString());
-        return new ByteArrayInputStream(bytes);
+        return new UnsynchronizedByteArrayInputStream(bytes);
     }
 }
diff --git 
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/rtf/RTFEmbObjHandler.java
 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/rtf/RTFEmbObjHandler.java
index 096a6f66c..040e78eae 100644
--- 
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/rtf/RTFEmbObjHandler.java
+++ 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/rtf/RTFEmbObjHandler.java
@@ -16,13 +16,13 @@
  */
 package org.apache.tika.parser.microsoft.rtf;
 
-import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.concurrent.atomic.AtomicInteger;
 
 import org.apache.commons.io.FilenameUtils;
 import org.apache.commons.io.IOUtils;
+import org.apache.commons.io.output.UnsynchronizedByteArrayOutputStream;
 import org.xml.sax.ContentHandler;
 import org.xml.sax.SAXException;
 
@@ -61,7 +61,7 @@ class RTFEmbObjHandler {
     private static final String EMPTY_STRING = "";
     private final ContentHandler handler;
     private final EmbeddedDocumentUtil embeddedDocumentUtil;
-    private final ByteArrayOutputStream os;
+    private final UnsynchronizedByteArrayOutputStream os;
     private final int memoryLimitInKb;
 
     private boolean isPictBitmap = false;
@@ -81,7 +81,7 @@ class RTFEmbObjHandler {
                                int memoryLimitInKb) {
         this.handler = handler;
         this.embeddedDocumentUtil = new EmbeddedDocumentUtil(context);
-        os = new ByteArrayOutputStream();
+        os = new UnsynchronizedByteArrayOutputStream();
         this.memoryLimitInKb = memoryLimitInKb;
     }
 
diff --git 
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/rtf/RTFObjDataParser.java
 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/rtf/RTFObjDataParser.java
index c4b3a280f..871e37a91 100644
--- 
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/rtf/RTFObjDataParser.java
+++ 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/rtf/RTFObjDataParser.java
@@ -18,8 +18,6 @@
 
 package org.apache.tika.parser.microsoft.rtf;
 
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
@@ -29,6 +27,8 @@ import java.util.concurrent.atomic.AtomicInteger;
 
 import org.apache.commons.io.FilenameUtils;
 import org.apache.commons.io.IOUtils;
+import org.apache.commons.io.input.UnsynchronizedByteArrayInputStream;
+import org.apache.commons.io.output.UnsynchronizedByteArrayOutputStream;
 import org.apache.poi.poifs.filesystem.DirectoryNode;
 import org.apache.poi.poifs.filesystem.DocumentEntry;
 import org.apache.poi.poifs.filesystem.DocumentInputStream;
@@ -85,7 +85,7 @@ class RTFObjDataParser {
      */
     protected byte[] parse(byte[] bytes, Metadata metadata, AtomicInteger 
unknownFilenameCount)
             throws IOException, TikaException {
-        ByteArrayInputStream is = new ByteArrayInputStream(bytes);
+        UnsynchronizedByteArrayInputStream is = new 
UnsynchronizedByteArrayInputStream(bytes);
         long version = readUInt(is);
         metadata.add(RTFMetadata.EMB_APP_VERSION, Long.toString(version));
 
@@ -119,7 +119,7 @@ class RTFObjDataParser {
             //simple bitmap bytes
             return embObjBytes;
         } else {
-            ByteArrayInputStream embIs = new ByteArrayInputStream(embObjBytes);
+            UnsynchronizedByteArrayInputStream embIs = new 
UnsynchronizedByteArrayInputStream(embObjBytes);
             boolean hasPoifs = false;
             try {
                 hasPoifs = hasPOIFSHeader(embIs);
@@ -155,7 +155,7 @@ class RTFObjDataParser {
 
             if (root.hasEntry("Package")) {
                 Entry ooxml = root.getEntry("Package");
-                ByteArrayOutputStream out = new ByteArrayOutputStream();
+                UnsynchronizedByteArrayOutputStream out = new 
UnsynchronizedByteArrayOutputStream();
                 try (BoundedInputStream bis = new 
BoundedInputStream(memoryLimitInKb * 1024,
                         new DocumentInputStream((DocumentEntry) ooxml))) {
                     IOUtils.copy(bis, out);
@@ -191,7 +191,7 @@ class RTFObjDataParser {
                     }
                 } else {
 
-                    ByteArrayOutputStream out = new ByteArrayOutputStream();
+                    UnsynchronizedByteArrayOutputStream out = new 
UnsynchronizedByteArrayOutputStream();
                     is.reset();
                     BoundedInputStream bis = new 
BoundedInputStream(memoryLimitInKb * 1024, is);
                     IOUtils.copy(is, out);
@@ -217,7 +217,7 @@ class RTFObjDataParser {
     private byte[] handlePackage(byte[] pkgBytes, Metadata metadata)
             throws IOException, TikaException {
         //now parse the package header
-        ByteArrayInputStream is = new ByteArrayInputStream(pkgBytes);
+        UnsynchronizedByteArrayInputStream is = new 
UnsynchronizedByteArrayInputStream(pkgBytes);
         readUShort(is);
 
         String displayName = readAnsiString(is);
diff --git 
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-miscoffice-module/src/main/java/org/apache/tika/parser/dbf/DBFCell.java
 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-miscoffice-module/src/main/java/org/apache/tika/parser/dbf/DBFCell.java
index 870e7d0aa..8c762c764 100644
--- 
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-miscoffice-module/src/main/java/org/apache/tika/parser/dbf/DBFCell.java
+++ 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-miscoffice-module/src/main/java/org/apache/tika/parser/dbf/DBFCell.java
@@ -16,7 +16,6 @@
  */
 package org.apache.tika.parser.dbf;
 
-import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.nio.charset.Charset;
@@ -30,6 +29,7 @@ import java.util.Locale;
 import java.util.TimeZone;
 
 import org.apache.commons.io.IOUtils;
+import org.apache.commons.io.input.UnsynchronizedByteArrayInputStream;
 
 import org.apache.tika.io.EndianUtils;
 
@@ -130,7 +130,7 @@ class DBFCell {
                 GregorianCalendar.getInstance(TimeZone.getTimeZone("UTC"), 
Locale.ROOT);
 //        baseCalendar.set(1899, 11, 31, 0, 0, 0);
         baseCalendar.set(-4712, 0, 1, 0, 0, 0);
-        try (InputStream is = new ByteArrayInputStream(getBytes())) {
+        try (InputStream is = new 
UnsynchronizedByteArrayInputStream(getBytes())) {
 
             int date = EndianUtils.readIntLE(is);
             int time = EndianUtils.readIntLE(is);
diff --git 
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pdf-module/src/main/java/org/apache/tika/parser/pdf/AbstractPDF2XHTML.java
 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pdf-module/src/main/java/org/apache/tika/parser/pdf/AbstractPDF2XHTML.java
index 95dd6565e..d4c832ec1 100644
--- 
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pdf-module/src/main/java/org/apache/tika/parser/pdf/AbstractPDF2XHTML.java
+++ 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pdf-module/src/main/java/org/apache/tika/parser/pdf/AbstractPDF2XHTML.java
@@ -23,7 +23,6 @@ import static 
org.apache.tika.parser.pdf.PDFParserConfig.OCR_STRATEGY.OCR_ONLY;
 
 import java.awt.image.BufferedImage;
 import java.io.BufferedInputStream;
-import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
@@ -48,6 +47,7 @@ import java.util.TreeSet;
 import javax.xml.stream.XMLStreamException;
 
 import org.apache.commons.io.IOUtils;
+import org.apache.commons.io.input.UnsynchronizedByteArrayInputStream;
 import org.apache.pdfbox.cos.COSDictionary;
 import org.apache.pdfbox.cos.COSName;
 import org.apache.pdfbox.pdmodel.PDDocument;
@@ -278,7 +278,7 @@ class AbstractPDF2XHTML extends PDFTextStripper {
                     EmbeddedDocumentUtil.recordEmbeddedStreamException(e, 
parentMetadata);
                 }
                 if (bytes != null) {
-                    try (InputStream is = new ByteArrayInputStream(bytes)) {
+                    try (InputStream is = new 
UnsynchronizedByteArrayInputStream(bytes)) {
                         parseMetadata(is, xfaMetadata);
                     }
                 }
@@ -1024,7 +1024,7 @@ class AbstractPDF2XHTML extends PDFTextStripper {
             XFAExtractor xfaExtractor = new XFAExtractor();
             InputStream is = null;
             try {
-                is = new BufferedInputStream(new 
ByteArrayInputStream(pdxfa.getBytes()));
+                is = new BufferedInputStream(new 
UnsynchronizedByteArrayInputStream(pdxfa.getBytes()));
             } catch (IOException e) {
                 EmbeddedDocumentUtil.recordEmbeddedStreamException(e, 
metadata);
             }
diff --git 
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pdf-module/src/main/java/org/apache/tika/parser/pdf/PDFEncodedStringDecoder.java
 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pdf-module/src/main/java/org/apache/tika/parser/pdf/PDFEncodedStringDecoder.java
index 7b8cd2fd0..255465ebb 100644
--- 
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pdf-module/src/main/java/org/apache/tika/parser/pdf/PDFEncodedStringDecoder.java
+++ 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pdf-module/src/main/java/org/apache/tika/parser/pdf/PDFEncodedStringDecoder.java
@@ -19,10 +19,10 @@ package org.apache.tika.parser.pdf;
 
 import static java.nio.charset.StandardCharsets.ISO_8859_1;
 
-import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 
+import org.apache.commons.io.input.UnsynchronizedByteArrayInputStream;
 import org.apache.pdfbox.cos.COSString;
 import org.apache.pdfbox.io.RandomAccessBuffer;
 import org.apache.pdfbox.io.RandomAccessRead;
@@ -82,7 +82,7 @@ class PDFEncodedStringDecoder {
     String decode(String value) {
         try {
             byte[] bytes = new String("(" + value + ")").getBytes(ISO_8859_1);
-            InputStream is = new ByteArrayInputStream(bytes);
+            InputStream is = new UnsynchronizedByteArrayInputStream(bytes);
             COSStringParser p = new COSStringParser(new 
RandomAccessBuffer(is));
             String parsed = p.myParseCOSString();
             if (parsed != null) {
diff --git 
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pdf-module/src/main/java/org/apache/tika/parser/pdf/PDFParser.java
 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pdf-module/src/main/java/org/apache/tika/parser/pdf/PDFParser.java
index 8ac380aa6..f5d11a1a3 100644
--- 
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pdf-module/src/main/java/org/apache/tika/parser/pdf/PDFParser.java
+++ 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pdf-module/src/main/java/org/apache/tika/parser/pdf/PDFParser.java
@@ -16,7 +16,6 @@
  */
 package org.apache.tika.parser.pdf;
 
-import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.nio.file.Path;
@@ -29,6 +28,7 @@ import java.util.Set;
 import javax.xml.stream.XMLStreamException;
 
 import org.apache.commons.io.input.CloseShieldInputStream;
+import org.apache.commons.io.input.UnsynchronizedByteArrayInputStream;
 import org.apache.pdfbox.cos.COSArray;
 import org.apache.pdfbox.cos.COSBase;
 import org.apache.pdfbox.cos.COSDictionary;
@@ -531,7 +531,7 @@ public class PDFParser extends AbstractParser implements 
RenderingParser, Initia
         XFAExtractor ex = new XFAExtractor();
         XHTMLContentHandler xhtml = new XHTMLContentHandler(handler, metadata);
         xhtml.startDocument();
-        try (InputStream is = new ByteArrayInputStream(
+        try (InputStream is = new UnsynchronizedByteArrayInputStream(
                 
pdDocument.getDocumentCatalog().getAcroForm(null).getXFA().getBytes())) {
             ex.extract(is, xhtml, metadata, context);
         } catch (XMLStreamException e) {
diff --git 
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pdf-module/src/main/java/org/apache/tika/parser/pdf/image/ImageGraphicsEngine.java
 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pdf-module/src/main/java/org/apache/tika/parser/pdf/image/ImageGraphicsEngine.java
index 769218a6a..f18727135 100644
--- 
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pdf-module/src/main/java/org/apache/tika/parser/pdf/image/ImageGraphicsEngine.java
+++ 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pdf-module/src/main/java/org/apache/tika/parser/pdf/image/ImageGraphicsEngine.java
@@ -18,7 +18,6 @@ package org.apache.tika.parser.pdf.image;
 
 import java.awt.geom.Point2D;
 import java.awt.image.BufferedImage;
-import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
@@ -29,6 +28,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.concurrent.atomic.AtomicInteger;
 
+import org.apache.commons.io.output.UnsynchronizedByteArrayOutputStream;
 import org.apache.pdfbox.contentstream.PDFGraphicsStreamEngine;
 import org.apache.pdfbox.cos.COSName;
 import org.apache.pdfbox.cos.COSStream;
@@ -410,7 +410,7 @@ public class ImageGraphicsEngine extends 
PDFGraphicsStreamEngine {
         }
 
         if (embeddedDocumentExtractor.shouldParseEmbedded(metadata)) {
-            ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+            UnsynchronizedByteArrayOutputStream buffer = new 
UnsynchronizedByteArrayOutputStream();
             if (pdImage instanceof PDImageXObject) {
                 //extract the metadata contained outside of the image
                 PDMetadataExtractor
diff --git 
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pkg-module/src/main/java/org/apache/tika/parser/pkg/PackageParser.java
 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pkg-module/src/main/java/org/apache/tika/parser/pkg/PackageParser.java
index b582a029d..25a91f74d 100644
--- 
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pkg-module/src/main/java/org/apache/tika/parser/pkg/PackageParser.java
+++ 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pkg-module/src/main/java/org/apache/tika/parser/pkg/PackageParser.java
@@ -27,7 +27,6 @@ import static org.apache.tika.detect.zip.PackageConstants.TAR;
 import static org.apache.tika.detect.zip.PackageConstants.ZIP;
 
 import java.io.BufferedInputStream;
-import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.nio.charset.Charset;
@@ -55,6 +54,7 @@ import 
org.apache.commons.compress.archivers.zip.UnsupportedZipFeatureException.
 import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
 import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
 import org.apache.commons.io.input.CloseShieldInputStream;
+import org.apache.commons.io.input.UnsynchronizedByteArrayInputStream;
 import org.xml.sax.ContentHandler;
 import org.xml.sax.SAXException;
 import org.xml.sax.helpers.AttributesImpl;
@@ -425,8 +425,9 @@ public class PackageParser extends 
AbstractEncodingDetectorParser {
         //Try to detect charset of archive entry in case of non-unicode 
filename is used
         if (detectCharsetsInEntryNames && entry instanceof ZipArchiveEntry) {
             Charset candidate =
-                    getEncodingDetector().detect(new 
ByteArrayInputStream(((ZipArchiveEntry) entry).getRawName()),
-                        parentMetadata);
+                    getEncodingDetector().detect(
+                            new 
UnsynchronizedByteArrayInputStream(((ZipArchiveEntry) entry).getRawName()),
+                            parentMetadata);
             if (candidate != null) {
                 name = new String(((ZipArchiveEntry) entry).getRawName(), 
candidate);
             }
diff --git 
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-text-module/src/main/java/org/apache/tika/parser/txt/CharsetMatch.java
 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-text-module/src/main/java/org/apache/tika/parser/txt/CharsetMatch.java
index faab4a5e1..2bab9037f 100644
--- 
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-text-module/src/main/java/org/apache/tika/parser/txt/CharsetMatch.java
+++ 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-text-module/src/main/java/org/apache/tika/parser/txt/CharsetMatch.java
@@ -8,12 +8,12 @@
  */
 package org.apache.tika.parser.txt;
 
-import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.Reader;
 
+import org.apache.commons.io.input.UnsynchronizedByteArrayInputStream;
 
 /**
  * This class represents a charset that has been identified by a 
CharsetDetector
@@ -99,7 +99,7 @@ public class CharsetMatch implements Comparable<CharsetMatch> 
{
         InputStream inputStream = fInputStream;
 
         if (inputStream == null) {
-            inputStream = new ByteArrayInputStream(fRawInput, 0, fRawLength);
+            inputStream = new UnsynchronizedByteArrayInputStream(fRawInput, 0, 
fRawLength);
         }
 
         try {
diff --git 
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-xml-module/src/main/java/org/apache/tika/parser/xml/FictionBookParser.java
 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-xml-module/src/main/java/org/apache/tika/parser/xml/FictionBookParser.java
index 6b4b8ba9c..52e9e069d 100644
--- 
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-xml-module/src/main/java/org/apache/tika/parser/xml/FictionBookParser.java
+++ 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-xml-module/src/main/java/org/apache/tika/parser/xml/FictionBookParser.java
@@ -16,12 +16,13 @@
  */
 package org.apache.tika.parser.xml;
 
-import java.io.ByteArrayInputStream;
 import java.io.IOException;
+import java.io.InputStream;
 import java.util.Collections;
 import java.util.Set;
 
 import org.apache.commons.codec.binary.Base64;
+import org.apache.commons.io.input.UnsynchronizedByteArrayInputStream;
 import org.xml.sax.Attributes;
 import org.xml.sax.ContentHandler;
 import org.xml.sax.SAXException;
@@ -85,10 +86,10 @@ public class FictionBookParser extends XMLParser {
         @Override
         public void endElement(String uri, String localName, String qName) 
throws SAXException {
             if (binaryMode) {
-                try {
+                try (InputStream stream =
+                             new 
UnsynchronizedByteArrayInputStream(Base64.decodeBase64(binaryData.toString()))) 
{
                     partExtractor.parseEmbedded(
-                            new 
ByteArrayInputStream(Base64.decodeBase64(binaryData.toString())),
-                            handler, metadata, true);
+                            stream, handler, metadata, true);
                 } catch (IOException e) {
                     throw new SAXException("IOException in parseEmbedded", e);
                 }
diff --git 
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-xmp-commons/src/main/java/org/apache/tika/parser/xmp/JempboxExtractor.java
 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-xmp-commons/src/main/java/org/apache/tika/parser/xmp/JempboxExtractor.java
index c2e87e1bb..6f791b3d5 100644
--- 
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-xmp-commons/src/main/java/org/apache/tika/parser/xmp/JempboxExtractor.java
+++ 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-xmp-commons/src/main/java/org/apache/tika/parser/xmp/JempboxExtractor.java
@@ -18,13 +18,12 @@ package org.apache.tika.parser.xmp;
 
 import static java.nio.charset.StandardCharsets.UTF_8;
 
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.Calendar;
 import java.util.List;
 
+import org.apache.commons.io.output.UnsynchronizedByteArrayOutputStream;
 import org.apache.jempbox.xmp.ResourceEvent;
 import org.apache.jempbox.xmp.ResourceRef;
 import org.apache.jempbox.xmp.XMPMetadata;
@@ -221,13 +220,13 @@ public class JempboxExtractor {
     }
 
     public void parse(InputStream file) throws IOException, TikaException {
-        ByteArrayOutputStream xmpraw = new ByteArrayOutputStream();
+        UnsynchronizedByteArrayOutputStream xmpraw = new 
UnsynchronizedByteArrayOutputStream();
         if (!scanner.parse(file, xmpraw)) {
             return;
         }
 
         XMPMetadata xmp = null;
-        try (InputStream decoded = new 
ByteArrayInputStream(xmpraw.toByteArray())) {
+        try (InputStream decoded = xmpraw.toInputStream()) {
             Document dom = XMLReaderUtils.buildDOM(decoded, 
EMPTY_PARSE_CONTEXT);
             if (dom != null) {
                 xmp = new XMPMetadata(dom);
diff --git 
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-zip-commons/src/main/java/org/apache/tika/detect/zip/DefaultZipContainerDetector.java
 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-zip-commons/src/main/java/org/apache/tika/detect/zip/DefaultZipContainerDetector.java
index fb0d5d8e1..3782c69fd 100644
--- 
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-zip-commons/src/main/java/org/apache/tika/detect/zip/DefaultZipContainerDetector.java
+++ 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-zip-commons/src/main/java/org/apache/tika/detect/zip/DefaultZipContainerDetector.java
@@ -17,7 +17,6 @@
 package org.apache.tika.detect.zip;
 
 import java.io.BufferedInputStream;
-import java.io.ByteArrayInputStream;
 import java.io.EOFException;
 import java.io.IOException;
 import java.io.InputStream;
@@ -35,6 +34,7 @@ import 
org.apache.commons.compress.compressors.CompressorException;
 import org.apache.commons.compress.compressors.CompressorStreamFactory;
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.io.input.CloseShieldInputStream;
+import org.apache.commons.io.input.UnsynchronizedByteArrayInputStream;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -121,7 +121,7 @@ public class DefaultZipContainerDetector implements 
Detector {
             return TIFF;
         }
         try {
-            String name = ArchiveStreamFactory.detect(new 
ByteArrayInputStream(prefix, 0, length));
+            String name = ArchiveStreamFactory.detect(new 
UnsynchronizedByteArrayInputStream(prefix, 0, length));
             return PackageConstants.getMediaType(name);
         } catch (ArchiveException e) {
             return MediaType.OCTET_STREAM;
@@ -131,7 +131,7 @@ public class DefaultZipContainerDetector implements 
Detector {
     static MediaType detectCompressorFormat(byte[] prefix, int length) {
         try {
             String type =
-                    CompressorStreamFactory.detect(new 
ByteArrayInputStream(prefix, 0, length));
+                    CompressorStreamFactory.detect(new 
UnsynchronizedByteArrayInputStream(prefix, 0, length));
             return CompressorConstants.getMediaType(type);
         } catch (CompressorException e) {
             return MediaType.OCTET_STREAM;
diff --git 
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-zip-commons/src/main/java/org/apache/tika/detect/zip/OpenDocumentDetector.java
 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-zip-commons/src/main/java/org/apache/tika/detect/zip/OpenDocumentDetector.java
index 218b2ff7e..a287c4b0b 100644
--- 
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-zip-commons/src/main/java/org/apache/tika/detect/zip/OpenDocumentDetector.java
+++ 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-zip-commons/src/main/java/org/apache/tika/detect/zip/OpenDocumentDetector.java
@@ -18,13 +18,13 @@ package org.apache.tika.detect.zip;
 
 import static java.nio.charset.StandardCharsets.UTF_8;
 
-import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 
 import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
 import org.apache.commons.compress.archivers.zip.ZipFile;
 import org.apache.commons.io.IOUtils;
+import org.apache.commons.io.output.UnsynchronizedByteArrayOutputStream;
 
 import org.apache.tika.io.BoundedInputStream;
 import org.apache.tika.io.TikaInputStream;
@@ -57,13 +57,13 @@ public class OpenDocumentDetector implements 
ZipContainerDetector {
         if ("mimetype".equals(name)) {
             //can't rely on zae.getSize to determine if there is any
             //content here. :(
-            ByteArrayOutputStream bos = new ByteArrayOutputStream();
+            UnsynchronizedByteArrayOutputStream bos = new 
UnsynchronizedByteArrayOutputStream();
             BoundedInputStream bis = new BoundedInputStream(MAX_MIME_TYPE, 
zis);
             IOUtils.copy(bis, bos);
             //do anything with an inputstream > MAX_MIME_TYPE?
-            if (bos.toByteArray().length > 0) {
+            if (bos.size() > 0) {
                 //odt -- TODO -- check that the results are valid
-                return MediaType.parse(new String(bos.toByteArray(), UTF_8));
+                return MediaType.parse(bos.toString(UTF_8));
             }
         }
         return null;
diff --git 
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-zip-commons/src/main/java/org/apache/tika/detect/zip/StarOfficeDetector.java
 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-zip-commons/src/main/java/org/apache/tika/detect/zip/StarOfficeDetector.java
index 728b1ec1c..028f6f3b3 100644
--- 
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-zip-commons/src/main/java/org/apache/tika/detect/zip/StarOfficeDetector.java
+++ 
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-zip-commons/src/main/java/org/apache/tika/detect/zip/StarOfficeDetector.java
@@ -16,8 +16,6 @@
  */
 package org.apache.tika.detect.zip;
 
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.HashMap;
@@ -26,6 +24,7 @@ import java.util.Map;
 import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
 import org.apache.commons.compress.archivers.zip.ZipFile;
 import org.apache.commons.io.IOUtils;
+import org.apache.commons.io.output.UnsynchronizedByteArrayOutputStream;
 import org.xml.sax.Attributes;
 import org.xml.sax.SAXException;
 import org.xml.sax.helpers.DefaultHandler;
@@ -92,11 +91,11 @@ public class StarOfficeDetector implements 
ZipContainerDetector {
         //"as is" can cause the iteration of the entries to stop early
         //without exception or warning.  So, copy the full stream, then
         //process.  TIKA-3061
-        ByteArrayOutputStream bos = new ByteArrayOutputStream();
+        UnsynchronizedByteArrayOutputStream bos = new 
UnsynchronizedByteArrayOutputStream();
         BoundedInputStream bis = new BoundedInputStream(MAX_MANIFEST, zis);
         IOUtils.copy(bis, bos);
 
-        return detectStarOfficeX(new ByteArrayInputStream(bos.toByteArray()));
+        return detectStarOfficeX(bos.toInputStream());
 
     }
 
diff --git 
a/tika-pipes/tika-emitters/tika-emitter-az-blob/src/main/java/org/apache/tika/pipes/emitter/azblob/AZBlobEmitter.java
 
b/tika-pipes/tika-emitters/tika-emitter-az-blob/src/main/java/org/apache/tika/pipes/emitter/azblob/AZBlobEmitter.java
index 0f8fbd1cd..83c18e3c4 100644
--- 
a/tika-pipes/tika-emitters/tika-emitter-az-blob/src/main/java/org/apache/tika/pipes/emitter/azblob/AZBlobEmitter.java
+++ 
b/tika-pipes/tika-emitters/tika-emitter-az-blob/src/main/java/org/apache/tika/pipes/emitter/azblob/AZBlobEmitter.java
@@ -18,8 +18,6 @@ package org.apache.tika.pipes.emitter.azblob;
 
 import static org.apache.tika.config.TikaConfig.mustNotBeEmpty;
 
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStreamWriter;
@@ -35,6 +33,8 @@ import com.azure.storage.blob.BlobContainerClient;
 import com.azure.storage.blob.BlobServiceClient;
 import com.azure.storage.blob.BlobServiceClientBuilder;
 import org.apache.commons.io.IOUtils;
+import org.apache.commons.io.input.UnsynchronizedByteArrayInputStream;
+import org.apache.commons.io.output.UnsynchronizedByteArrayOutputStream;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -87,7 +87,7 @@ public class AZBlobEmitter extends AbstractEmitter implements 
Initializable, Str
         }
         //TODO: estimate size of metadata list.  Above a certain size,
         //create a temp file?
-        ByteArrayOutputStream bos = new ByteArrayOutputStream();
+        UnsynchronizedByteArrayOutputStream bos = new 
UnsynchronizedByteArrayOutputStream();
         try (Writer writer = new OutputStreamWriter(bos, 
StandardCharsets.UTF_8)) {
             JsonMetadataList.toJson(metadataList, writer);
         } catch (IOException e) {
@@ -126,9 +126,10 @@ public class AZBlobEmitter extends AbstractEmitter 
implements Initializable, Str
             LOGGER.debug("relying on the content-length set in the metadata 
object: {}", length);
             write(path, userMetadata, is, length);
         } else {
-            ByteArrayOutputStream bos = new ByteArrayOutputStream();
-            IOUtils.copy(is, bos);
-            write(path, userMetadata, bos.toByteArray());
+            try (UnsynchronizedByteArrayOutputStream bos = new 
UnsynchronizedByteArrayOutputStream()) {
+                IOUtils.copy(is, bos);
+                write(path, userMetadata, bos.toByteArray());
+            }
         }
     }
 
@@ -154,7 +155,7 @@ public class AZBlobEmitter extends AbstractEmitter 
implements Initializable, Str
         LOGGER.debug("about to emit to target container: ({}) path:({})", 
container, actualPath);
         BlobClient blobClient = blobContainerClient.getBlobClient(actualPath);
         updateMetadata(blobClient, userMetadata);
-        blobClient.upload(new ByteArrayInputStream(bytes), bytes.length, 
overwriteExisting);
+        blobClient.upload(new UnsynchronizedByteArrayInputStream(bytes), 
bytes.length, overwriteExisting);
     }
 
     private void updateMetadata(BlobClient blobClient, Metadata userMetadata) {
diff --git 
a/tika-pipes/tika-emitters/tika-emitter-gcs/src/main/java/org/apache/tika/pipes/emitter/gcs/GCSEmitter.java
 
b/tika-pipes/tika-emitters/tika-emitter-gcs/src/main/java/org/apache/tika/pipes/emitter/gcs/GCSEmitter.java
index e4c03c4f8..38757a87a 100644
--- 
a/tika-pipes/tika-emitters/tika-emitter-gcs/src/main/java/org/apache/tika/pipes/emitter/gcs/GCSEmitter.java
+++ 
b/tika-pipes/tika-emitters/tika-emitter-gcs/src/main/java/org/apache/tika/pipes/emitter/gcs/GCSEmitter.java
@@ -18,7 +18,6 @@ package org.apache.tika.pipes.emitter.gcs;
 
 import static org.apache.tika.config.TikaConfig.mustNotBeEmpty;
 
-import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStreamWriter;
@@ -33,6 +32,7 @@ import com.google.cloud.storage.BlobInfo;
 import com.google.cloud.storage.Storage;
 import com.google.cloud.storage.StorageOptions;
 import org.apache.commons.io.IOUtils;
+import org.apache.commons.io.output.UnsynchronizedByteArrayOutputStream;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -74,14 +74,15 @@ public class GCSEmitter extends AbstractEmitter implements 
Initializable, Stream
         if (metadataList == null || metadataList.size() == 0) {
             throw new TikaEmitterException("metadata list must not be null or 
of size 0");
         }
-        ByteArrayOutputStream bos = new ByteArrayOutputStream();
-        try (Writer writer = new OutputStreamWriter(bos, 
StandardCharsets.UTF_8)) {
-            JsonMetadataList.toJson(metadataList, writer);
-        } catch (IOException e) {
-            throw new TikaEmitterException("can't jsonify", e);
-        }
+        try (UnsynchronizedByteArrayOutputStream bos = new 
UnsynchronizedByteArrayOutputStream()) {
+            try (Writer writer = new OutputStreamWriter(bos, 
StandardCharsets.UTF_8)) {
+                JsonMetadataList.toJson(metadataList, writer);
+            } catch (IOException e) {
+                throw new TikaEmitterException("can't jsonify", e);
+            }
 
-        write(emitKey, new Metadata(), bos.toByteArray());
+            write(emitKey, new Metadata(), bos.toByteArray());
+        }
 
     }
 
@@ -98,9 +99,10 @@ public class GCSEmitter extends AbstractEmitter implements 
Initializable, Stream
         if (is instanceof TikaInputStream && ((TikaInputStream) is).hasFile()) 
{
             write(path, userMetadata, Files.readAllBytes(((TikaInputStream) 
is).getPath()));
         } else {
-            ByteArrayOutputStream bos = new ByteArrayOutputStream();
-            IOUtils.copy(is, bos);
-            write(path, userMetadata, bos.toByteArray());
+            try (UnsynchronizedByteArrayOutputStream bos = new 
UnsynchronizedByteArrayOutputStream()) {
+                IOUtils.copy(is, bos);
+                write(path, userMetadata, bos.toByteArray());
+            }
         }
     }
 
diff --git 
a/tika-pipes/tika-emitters/tika-emitter-opensearch/src/main/java/org/apache/tika/pipes/emitter/opensearch/OpenSearchClient.java
 
b/tika-pipes/tika-emitters/tika-emitter-opensearch/src/main/java/org/apache/tika/pipes/emitter/opensearch/OpenSearchClient.java
index 4dd163654..3eff65997 100644
--- 
a/tika-pipes/tika-emitters/tika-emitter-opensearch/src/main/java/org/apache/tika/pipes/emitter/opensearch/OpenSearchClient.java
+++ 
b/tika-pipes/tika-emitters/tika-emitter-opensearch/src/main/java/org/apache/tika/pipes/emitter/opensearch/OpenSearchClient.java
@@ -33,7 +33,7 @@ import org.apache.http.HttpResponse;
 import org.apache.http.client.HttpClient;
 import org.apache.http.client.methods.CloseableHttpResponse;
 import org.apache.http.client.methods.HttpPost;
-import org.apache.http.entity.ByteArrayEntity;
+import org.apache.http.entity.StringEntity;
 import org.apache.http.util.EntityUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -193,7 +193,7 @@ public class OpenSearchClient {
 
     public JsonResponse postJson(String url, String json) throws IOException {
         HttpPost httpRequest = new HttpPost(url);
-        ByteArrayEntity entity = new 
ByteArrayEntity(json.getBytes(StandardCharsets.UTF_8));
+        StringEntity entity = new StringEntity(json, StandardCharsets.UTF_8);
         httpRequest.setEntity(entity);
         httpRequest.setHeader("Accept", "application/json");
         httpRequest.setHeader("Content-type", "application/json; 
charset=utf-8");
diff --git 
a/tika-pipes/tika-emitters/tika-emitter-s3/src/main/java/org/apache/tika/pipes/emitter/s3/S3Emitter.java
 
b/tika-pipes/tika-emitters/tika-emitter-s3/src/main/java/org/apache/tika/pipes/emitter/s3/S3Emitter.java
index 7d2663c1f..9190c5880 100644
--- 
a/tika-pipes/tika-emitters/tika-emitter-s3/src/main/java/org/apache/tika/pipes/emitter/s3/S3Emitter.java
+++ 
b/tika-pipes/tika-emitters/tika-emitter-s3/src/main/java/org/apache/tika/pipes/emitter/s3/S3Emitter.java
@@ -19,7 +19,6 @@ package org.apache.tika.pipes.emitter.s3;
 import static org.apache.tika.config.TikaConfig.mustNotBeEmpty;
 
 import java.io.BufferedWriter;
-import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStreamWriter;
@@ -40,6 +39,7 @@ import com.amazonaws.services.s3.AmazonS3;
 import com.amazonaws.services.s3.AmazonS3ClientBuilder;
 import com.amazonaws.services.s3.model.ObjectMetadata;
 import com.amazonaws.services.s3.model.PutObjectRequest;
+import org.apache.commons.io.output.UnsynchronizedByteArrayOutputStream;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -120,7 +120,7 @@ public class S3Emitter extends AbstractEmitter implements 
Initializable, StreamE
         }
 
         if (!spoolToTemp) {
-            ByteArrayOutputStream bos = new ByteArrayOutputStream();
+            UnsynchronizedByteArrayOutputStream bos = new 
UnsynchronizedByteArrayOutputStream();
             try (Writer writer = new BufferedWriter(
                     new OutputStreamWriter(bos, StandardCharsets.UTF_8))) {
                 JsonMetadataList.toJson(metadataList, writer);
diff --git 
a/tika-pipes/tika-fetchers/tika-fetcher-http/src/main/java/org/apache/tika/pipes/fetcher/http/HttpFetcher.java
 
b/tika-pipes/tika-fetchers/tika-fetcher-http/src/main/java/org/apache/tika/pipes/fetcher/http/HttpFetcher.java
index 2ef4ea49c..6d555e3aa 100644
--- 
a/tika-pipes/tika-fetchers/tika-fetcher-http/src/main/java/org/apache/tika/pipes/fetcher/http/HttpFetcher.java
+++ 
b/tika-pipes/tika-fetchers/tika-fetcher-http/src/main/java/org/apache/tika/pipes/fetcher/http/HttpFetcher.java
@@ -17,7 +17,6 @@
 package org.apache.tika.pipes.fetcher.http;
 
 
-import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
@@ -38,6 +37,7 @@ import java.util.TimerTask;
 import java.util.concurrent.atomic.AtomicBoolean;
 
 import org.apache.commons.io.IOUtils;
+import org.apache.commons.io.output.UnsynchronizedByteArrayOutputStream;
 import org.apache.http.ConnectionClosedException;
 import org.apache.http.Header;
 import org.apache.http.HttpConnection;
@@ -310,9 +310,9 @@ public class HttpFetcher extends AbstractFetcher implements 
Initializable, Range
             return "";
         }
         try (InputStream is = response.getEntity().getContent()) {
-            ByteArrayOutputStream bos = new ByteArrayOutputStream();
+            UnsynchronizedByteArrayOutputStream bos = new 
UnsynchronizedByteArrayOutputStream();
             IOUtils.copyLarge(is, bos, 0, maxErrMsgSize);
-            return new String(bos.toByteArray(), StandardCharsets.UTF_8);
+            return bos.toString(StandardCharsets.UTF_8);
         } catch (IOException e) {
             LOG.warn("IOException trying to read error message", e);
             return "";
diff --git 
a/tika-pipes/tika-httpclient-commons/src/main/java/org/apache/tika/client/HttpClientUtil.java
 
b/tika-pipes/tika-httpclient-commons/src/main/java/org/apache/tika/client/HttpClientUtil.java
index 3de32da8e..c16308a8d 100644
--- 
a/tika-pipes/tika-httpclient-commons/src/main/java/org/apache/tika/client/HttpClientUtil.java
+++ 
b/tika-pipes/tika-httpclient-commons/src/main/java/org/apache/tika/client/HttpClientUtil.java
@@ -23,6 +23,7 @@ import org.apache.http.HttpResponse;
 import org.apache.http.client.HttpClient;
 import org.apache.http.client.methods.HttpPost;
 import org.apache.http.entity.ByteArrayEntity;
+import org.apache.http.entity.StringEntity;
 import org.apache.http.util.EntityUtils;
 
 public class HttpClientUtil {
@@ -31,7 +32,7 @@ public class HttpClientUtil {
             throws IOException, TikaClientException {
         HttpPost post = new HttpPost(url);
         post.setHeader("Content-Encoding", "gzip");
-        ByteArrayEntity entity = new 
ByteArrayEntity(json.getBytes(StandardCharsets.UTF_8));
+        StringEntity entity = new StringEntity(json, StandardCharsets.UTF_8);
 
         post.setEntity(entity);
         post.setHeader("Content-Type", "application/json");
diff --git 
a/tika-server/tika-server-client/src/main/java/org/apache/tika/server/client/TikaPipesHttpClient.java
 
b/tika-server/tika-server-client/src/main/java/org/apache/tika/server/client/TikaPipesHttpClient.java
index 4e712646d..24a4ae4be 100644
--- 
a/tika-server/tika-server-client/src/main/java/org/apache/tika/server/client/TikaPipesHttpClient.java
+++ 
b/tika-server/tika-server-client/src/main/java/org/apache/tika/server/client/TikaPipesHttpClient.java
@@ -23,7 +23,7 @@ import org.apache.http.HttpResponse;
 import org.apache.http.client.HttpClient;
 import org.apache.http.client.methods.HttpGet;
 import org.apache.http.client.methods.HttpPost;
-import org.apache.http.entity.ByteArrayEntity;
+import org.apache.http.entity.StringEntity;
 import org.apache.http.impl.client.CloseableHttpClient;
 import org.apache.http.util.EntityUtils;
 import org.slf4j.Logger;
@@ -89,8 +89,7 @@ class TikaPipesHttpClient {
 
     private TikaEmitterResult postJson(String endPoint, String jsonRequest) {
         HttpPost post = new HttpPost(endPoint);
-        ByteArrayEntity entity = new 
ByteArrayEntity(jsonRequest.getBytes(StandardCharsets.UTF_8));
-        post.setEntity(entity);
+        post.setEntity(new StringEntity(jsonRequest, StandardCharsets.UTF_8));
         post.setHeader("Content-Type", "application/json");
 
         int tries = 0;

Reply via email to