Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoerg Kubitz2021-04-29 10:26:44 +0000
committerManoj Palat2021-06-11 06:31:17 +0000
commit574cc2ed536eaea4089c76940d123e90ce2894b0 (patch)
treeb6dc8b2afdad40026e5194b29639059f3bcb9f1b
parent6331a5e937a519ac3d67c4d2a2f6a60886d7ab5d (diff)
downloadeclipse.jdt.core-574cc2ed536eaea4089c76940d123e90ce2894b0.tar.gz
eclipse.jdt.core-574cc2ed536eaea4089c76940d123e90ce2894b0.tar.xz
eclipse.jdt.core-574cc2ed536eaea4089c76940d123e90ce2894b0.zip
Bug 573239 - [performance] improve Util.getInputStreamAsByteArray
Change-Id: If8cae64c24dddb86a435061d4c51a93361575969 Signed-off-by: Joerg Kubitz <jkubitz-eclipse@gmx.de> Reviewed-on: https://git.eclipse.org/r/c/jdt/eclipse.jdt.core/+/179974 Reviewed-by: Sravan Kumar Lakkimsetti <sravankumarl@in.ibm.com> Reviewed-by: Manoj Palat <manpalat@in.ibm.com> Tested-by: JDT Bot <jdt-bot@eclipse.org>
-rw-r--r--org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/util/Util.java2
-rw-r--r--org.eclipse.jdt.compiler.tool/src/org/eclipse/jdt/internal/compiler/tool/Util.java2
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileReader.java2
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java6
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/Util.java147
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/core/ToolFactory.java2
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElement.java2
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Util.java2
-rw-r--r--org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/nd/java/model/BinaryModuleFactory.java2
-rw-r--r--org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/nd/java/model/BinaryTypeFactory.java2
10 files changed, 89 insertions, 80 deletions
diff --git a/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/util/Util.java b/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/util/Util.java
index 2ed71fefad..558064c3cd 100644
--- a/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/util/Util.java
+++ b/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/util/Util.java
@@ -132,7 +132,7 @@ public final class Util {
}
CharsetDecoder charsetDecoder = charset.newDecoder();
charsetDecoder.onMalformedInput(CodingErrorAction.REPLACE).onUnmappableCharacter(CodingErrorAction.REPLACE);
- byte[] contents = org.eclipse.jdt.internal.compiler.util.Util.getInputStreamAsByteArray(stream, length);
+ byte[] contents = org.eclipse.jdt.internal.compiler.util.Util.getInputStreamAsByteArray(stream);
ByteBuffer byteBuffer = ByteBuffer.allocate(contents.length);
byteBuffer.put(contents);
byteBuffer.flip();
diff --git a/org.eclipse.jdt.compiler.tool/src/org/eclipse/jdt/internal/compiler/tool/Util.java b/org.eclipse.jdt.compiler.tool/src/org/eclipse/jdt/internal/compiler/tool/Util.java
index 04b74303c6..203b28370d 100644
--- a/org.eclipse.jdt.compiler.tool/src/org/eclipse/jdt/internal/compiler/tool/Util.java
+++ b/org.eclipse.jdt.compiler.tool/src/org/eclipse/jdt/internal/compiler/tool/Util.java
@@ -132,7 +132,7 @@ public final class Util {
}
CharsetDecoder charsetDecoder = charset.newDecoder();
charsetDecoder.onMalformedInput(CodingErrorAction.REPLACE).onUnmappableCharacter(CodingErrorAction.REPLACE);
- byte[] contents = org.eclipse.jdt.internal.compiler.util.Util.getInputStreamAsByteArray(stream, length);
+ byte[] contents = org.eclipse.jdt.internal.compiler.util.Util.getInputStreamAsByteArray(stream);
ByteBuffer byteBuffer = ByteBuffer.allocate(contents.length);
byteBuffer.put(contents);
byteBuffer.flip();
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileReader.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileReader.java
index ef195e64da..002fb41f9f 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileReader.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileReader.java
@@ -122,7 +122,7 @@ public static ClassFileReader read(InputStream stream, String fileName) throws C
}
public static ClassFileReader read(InputStream stream, String fileName, boolean fullyInitialize) throws ClassFormatException, IOException {
- byte classFileBytes[] = Util.getInputStreamAsByteArray(stream, -1);
+ byte classFileBytes[] = Util.getInputStreamAsByteArray(stream);
ClassFileReader classFileReader = new ClassFileReader(classFileBytes, fileName.toCharArray());
if (fullyInitialize) {
classFileReader.initialize();
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java
index fe178b173c..4a39060349 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java
@@ -705,7 +705,7 @@ public class Parser implements TerminalTokens, ParserBasicInformation, Conflicte
byte[] bytes = null;
try {
stream = new BufferedInputStream(stream);
- bytes = Util.getInputStreamAsByteArray(stream, -1);
+ bytes = Util.getInputStreamAsByteArray(stream);
} finally {
try {
stream.close();
@@ -726,7 +726,7 @@ public class Parser implements TerminalTokens, ParserBasicInformation, Conflicte
byte[] bytes = null;
try {
stream = new BufferedInputStream(stream);
- bytes = Util.getInputStreamAsByteArray(stream, -1);
+ bytes = Util.getInputStreamAsByteArray(stream);
} finally {
try {
stream.close();
@@ -806,7 +806,7 @@ public class Parser implements TerminalTokens, ParserBasicInformation, Conflicte
byte[] bytes = null;
try {
stream = new BufferedInputStream(stream);
- bytes = Util.getInputStreamAsByteArray(stream, -1);
+ bytes = Util.getInputStreamAsByteArray(stream);
} finally {
try {
stream.close();
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/Util.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/Util.java
index c5227433dd..3d50aca7f5 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/Util.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/Util.java
@@ -28,6 +28,7 @@ import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -400,7 +401,7 @@ public class Util implements SuffixConstants {
InputStream stream = null;
try {
stream = new BufferedInputStream(new FileInputStream(file));
- return getInputStreamAsByteArray(stream, (int) file.length());
+ return getInputStreamAsByteArray(stream);
} finally {
if (stream != null) {
try {
@@ -460,82 +461,90 @@ public class Util implements SuffixConstants {
}
}
- /*
- * NIO support to get input stream as byte array.
- * Not used as with JDK 1.4.2 this support is slower than standard IO one...
- * Keep it as comment for future in case of next JDK versions improve performance
- * in this area...
- *
- public static byte[] getInputStreamAsByteArray(FileInputStream stream, int length)
- throws IOException {
-
- FileChannel channel = stream.getChannel();
- int size = (int)channel.size();
- if (length >= 0 && length < size) size = length;
- byte[] contents = new byte[size];
- ByteBuffer buffer = ByteBuffer.wrap(contents);
- channel.read(buffer);
- return contents;
- }
- */
/**
* Returns the given input stream's contents as a byte array.
- * If a length is specified (i.e. if length != -1), only length bytes
- * are returned. Otherwise all bytes in the stream are returned.
+ * All bytes in the stream are returned.
* Note this doesn't close the stream.
- * @throws IOException if a problem occured reading the stream.
+ * @throws IOException if a problem occurred reading the stream.
*/
- public static byte[] getInputStreamAsByteArray(InputStream stream, int length)
- throws IOException {
- byte[] contents;
- if (length == -1) {
- contents = new byte[0];
- int contentsLength = 0;
- int amountRead = -1;
- do {
- int amountRequested = Math.max(stream.available(), DEFAULT_READING_SIZE); // read at least 8K
-
- // resize contents if needed
- if (contentsLength + amountRequested > contents.length) {
- System.arraycopy(
- contents,
- 0,
- contents = new byte[contentsLength + amountRequested],
- 0,
- contentsLength);
- }
-
- // read as many bytes as possible
- amountRead = stream.read(contents, contentsLength, amountRequested);
+ public static byte[] getInputStreamAsByteArray(InputStream input) throws IOException {
+ if (input instanceof ByteArrayInputStream) {
+ // not available in java 8: ((ByteArrayInputStream) input).readAllBytes();
+ int length = ((ByteArrayInputStream) input).available();
+ return readNBytes(input, length);
+ }
+ if (input instanceof FileInputStream) {
+ long length = ((FileInputStream) input).getChannel().size();
+ return readNBytes(input, length);
+ }
+ return readAllBytes(input);
+ }
- if (amountRead > 0) {
- // remember length of contents
- contentsLength += amountRead;
- }
- } while (amountRead != -1);
-
- // resize contents if necessary
- if (contentsLength < contents.length) {
- System.arraycopy(
- contents,
- 0,
- contents = new byte[contentsLength],
- 0,
- contentsLength);
+ private static byte[] readAllBytes(InputStream input) throws IOException {
+ ArrayList<byte[]> byteBufList = new ArrayList<byte[]>(3);
+ int totalByteCount = 0;
+ int bytesJustRead;
+ do {
+ int bufLength = Math.max(input.available(), DEFAULT_READING_SIZE); // read at least 8K
+ byte[] byteBuf = new byte[bufLength];
+ int bytesInBuf = 0;
+ int byteTransferSize = bufLength;
+ while ((bytesJustRead = input.read(byteBuf, bytesInBuf, byteTransferSize)) >= 0) {
+ bytesInBuf += bytesJustRead;
+ totalByteCount += bytesJustRead;
+ byteTransferSize = bufLength - bytesInBuf;
+ if (byteTransferSize <= 0)
+ break;
}
- } else {
- contents = new byte[length];
- int len = 0;
- int readSize = 0;
- while ((readSize != -1) && (len != length)) {
- // See PR 1FMS89U
- // We record first the read size. In this case len is the actual read size.
- len += readSize;
- readSize = stream.read(contents, len, length - len);
+ if (bytesInBuf>0)
+ byteBufList.add(byteBuf);
+ } while (bytesJustRead >= 0);
+ // final concatenation of buffers:
+ if (byteBufList.size()==1) {
+ byte[] firstBuf = byteBufList.get(0);
+ if (firstBuf.length >= totalByteCount) { // fast path
+ return (firstBuf.length == totalByteCount) ? firstBuf : Arrays.copyOf(firstBuf, totalByteCount);
}
}
+ byte[] result = new byte[totalByteCount];
+ int byteCount = 0;
+ for (byte[] byteBuf : byteBufList) {
+ int byteTransferSize = Math.min(totalByteCount - byteCount, byteBuf.length);
+ System.arraycopy(byteBuf, 0, result, byteCount, byteTransferSize);
+ byteCount += byteTransferSize;
+ }
+ return result;
+ }
- return contents;
+ public static final int MAX_ARRAY_LENGTH = Integer.MAX_VALUE - 8;
+
+ public static byte[] readNBytes(java.io.InputStream input, long length) throws IOException {
+ if (length > MAX_ARRAY_LENGTH) // fail fast
+ throw new OutOfMemoryError("File too large for array: " + length); //$NON-NLS-1$
+ return readNBytes(input, (int) length);
+ }
+
+ /**
+ * Returns the given input stream's first bytes as array.
+ * Note this doesn't close the stream.
+ * @throws IOException if a problem occurred reading the stream.
+ */
+ public static byte[] readNBytes(InputStream input, int byteLength) throws IOException {
+ // InputStream.readNBytes() only available after java 11
+ if (byteLength == 0)
+ return new byte[0];
+ byte[] byteBuf = new byte[byteLength]; // exact buffer size
+ int byteCount = 0;
+ int byteTransferSize = byteBuf.length;
+ int bytesRead;
+ while ((bytesRead = input.read(byteBuf, byteCount, byteTransferSize)) >= 0) {
+ byteCount += bytesRead;
+ byteTransferSize = byteBuf.length - byteCount;
+ if (byteTransferSize <= 0) {
+ break;
+ }
+ }
+ return (byteBuf.length == byteCount) ? byteBuf : Arrays.copyOf(byteBuf, byteCount);
}
/**
@@ -665,7 +674,7 @@ public class Util implements SuffixConstants {
InputStream inputStream = zip.getInputStream(ze);
if (inputStream == null) throw new IOException("Invalid zip entry name : " + ze.getName()); //$NON-NLS-1$
stream = new BufferedInputStream(inputStream);
- return getInputStreamAsByteArray(stream, (int) ze.getSize());
+ return readNBytes(stream, (int) ze.getSize());
} finally {
if (stream != null) {
try {
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ToolFactory.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ToolFactory.java
index 2ed3678dcd..1e573c76d3 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ToolFactory.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ToolFactory.java
@@ -311,7 +311,7 @@ public class ToolFactory {
*/
public static IClassFileReader createDefaultClassFileReader(InputStream stream, int decodingFlag) {
try {
- return new ClassFileReader(Util.getInputStreamAsByteArray(stream, -1), decodingFlag);
+ return new ClassFileReader(Util.getInputStreamAsByteArray(stream), decodingFlag);
} catch(ClassFormatException | IOException e) {
return null;
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElement.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElement.java
index 8266ab47fb..719a586dfe 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElement.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElement.java
@@ -891,7 +891,7 @@ public abstract class JavaElement extends PlatformObject implements IJavaElement
stream = new BufferedInputStream(connection.getInputStream());
String encoding = connection.getContentEncoding();
- byte[] contents = org.eclipse.jdt.internal.compiler.util.Util.getInputStreamAsByteArray(stream, connection.getContentLength());
+ byte[] contents = org.eclipse.jdt.internal.compiler.util.Util.getInputStreamAsByteArray(stream);
if (encoding == null) {
int index = getIndexOf(contents, META_START, 0, -1);
if (index != -1) {
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Util.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Util.java
index 9f602c6ebc..c53b6feb28 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Util.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Util.java
@@ -1159,7 +1159,7 @@ public class Util {
throw new JavaModelException(e);
}
try {
- return org.eclipse.jdt.internal.compiler.util.Util.getInputStreamAsByteArray(stream, -1);
+ return org.eclipse.jdt.internal.compiler.util.Util.getInputStreamAsByteArray(stream);
} catch (IOException e) {
throw new JavaModelException(e, IJavaModelStatusConstants.IO_EXCEPTION);
} finally {
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/nd/java/model/BinaryModuleFactory.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/nd/java/model/BinaryModuleFactory.java
index 0733edb72f..2edf3ec8c2 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/nd/java/model/BinaryModuleFactory.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/nd/java/model/BinaryModuleFactory.java
@@ -149,7 +149,7 @@ public class BinaryModuleFactory {
IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(new String(descriptor.workspacePath)));
byte[] contents;
try (InputStream stream = file.getContents(true)) {
- contents = org.eclipse.jdt.internal.compiler.util.Util.getInputStreamAsByteArray(stream, -1);
+ contents = org.eclipse.jdt.internal.compiler.util.Util.getInputStreamAsByteArray(stream);
} catch (CoreException e) {
IStatus status = e.getStatus();
if (status.getCode() == IResourceStatus.RESOURCE_NOT_FOUND) {
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/nd/java/model/BinaryTypeFactory.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/nd/java/model/BinaryTypeFactory.java
index 9b0558599b..bfb48e34fe 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/nd/java/model/BinaryTypeFactory.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/nd/java/model/BinaryTypeFactory.java
@@ -188,7 +188,7 @@ public class BinaryTypeFactory {
IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(new String(descriptor.workspacePath)));
byte[] contents;
try (InputStream stream = file.getContents(true)) {
- contents = org.eclipse.jdt.internal.compiler.util.Util.getInputStreamAsByteArray(stream, -1);
+ contents = org.eclipse.jdt.internal.compiler.util.Util.getInputStreamAsByteArray(stream);
} catch (CoreException e) {
IStatus status = e.getStatus();
if (status.getCode() == IResourceStatus.RESOURCE_NOT_FOUND) {

Back to the top