8277501: Revisit PathFileObject.getCharContent and friends

Reviewed-by: vromero, jjg
This commit is contained in:
Archie L. Cobbs 2023-03-31 23:17:56 +00:00 committed by Vicente Romero
parent abfb900829
commit 8eb4e7e07e
3 changed files with 58 additions and 65 deletions

View File

@ -75,10 +75,12 @@ import com.sun.tools.javac.util.Options;
* java.io.File or java.nio.file.Path. * java.io.File or java.nio.file.Path.
*/ */
public abstract class BaseFileManager implements JavaFileManager { public abstract class BaseFileManager implements JavaFileManager {
private static final byte[] EMPTY_ARRAY = new byte[0];
@SuppressWarnings("this-escape") @SuppressWarnings("this-escape")
protected BaseFileManager(Charset charset) { protected BaseFileManager(Charset charset) {
this.charset = charset; this.charset = charset;
byteBufferCache = new ByteBufferCache();
locations = createLocations(); locations = createLocations();
} }
@ -403,56 +405,33 @@ public abstract class BaseFileManager implements JavaFileManager {
// <editor-fold defaultstate="collapsed" desc="ByteBuffers"> // <editor-fold defaultstate="collapsed" desc="ByteBuffers">
/** /**
* Make a byte buffer from an input stream. * Make a {@link ByteBuffer} from an input stream.
* @param in the stream * @param in the stream
* @return a byte buffer containing the contents of the stream * @return a byte buffer containing the contents of the stream
* @throws IOException if an error occurred while reading the stream * @throws IOException if an error occurred while reading the stream
*/ */
public ByteBuffer makeByteBuffer(InputStream in) public ByteBuffer makeByteBuffer(InputStream in) throws IOException {
throws IOException { byte[] array;
int limit = in.available(); synchronized (this) {
if (limit < 1024) limit = 1024; if ((array = byteArrayCache) != null)
ByteBuffer result = byteBufferCache.get(limit); byteArrayCache = null;
int position = 0; else
while (in.available() != 0) { array = EMPTY_ARRAY;
if (position >= limit)
// expand buffer
result = ByteBuffer.
allocate(limit <<= 1).
put(result.flip());
int count = in.read(result.array(),
position,
limit - position);
if (count < 0) break;
result.position(position += count);
} }
return result.flip(); com.sun.tools.javac.util.ByteBuffer buf = new com.sun.tools.javac.util.ByteBuffer(array);
buf.appendStream(in);
return buf.asByteBuffer();
} }
public void recycleByteBuffer(ByteBuffer bb) { public void recycleByteBuffer(ByteBuffer buf) {
byteBufferCache.put(bb); if (buf.hasArray()) {
} synchronized (this) {
byteArrayCache = buf.array();
/** }
* A single-element cache of direct byte buffers.
*/
private static class ByteBufferCache {
private ByteBuffer cached;
ByteBuffer get(int capacity) {
if (capacity < 20480) capacity = 20480;
ByteBuffer result =
(cached != null && cached.capacity() >= capacity)
? cached.clear()
: ByteBuffer.allocate(capacity);
cached = null;
return result;
}
void put(ByteBuffer x) {
cached = x;
} }
} }
private final ByteBufferCache byteBufferCache; private byte[] byteArrayCache;
// </editor-fold> // </editor-fold>
// <editor-fold defaultstate="collapsed" desc="Content cache"> // <editor-fold defaultstate="collapsed" desc="Content cache">

View File

@ -2741,7 +2741,9 @@ public class ClassReader {
try { try {
bp = 0; bp = 0;
buf.reset(); buf.reset();
buf.appendStream(c.classfile.openInputStream()); try (InputStream input = c.classfile.openInputStream()) {
buf.appendStream(input);
}
readClassBuffer(c); readClassBuffer(c);
if (!missingTypeVariables.isEmpty() && !foundTypeVariables.isEmpty()) { if (!missingTypeVariables.isEmpty() && !foundTypeVariables.isEmpty()) {
List<Type> missing = missingTypeVariables; List<Type> missing = missingTypeVariables;

View File

@ -56,8 +56,13 @@ public class ByteBuffer {
* of given size. * of given size.
*/ */
public ByteBuffer(int initialSize) { public ByteBuffer(int initialSize) {
elems = new byte[initialSize]; this(new byte[initialSize]);
length = 0; }
/** Create a new byte buffer using the given array for storage.
*/
public ByteBuffer(byte[] elems) {
this.elems = elems;
} }
/** Append byte to this buffer. /** Append byte to this buffer.
@ -147,30 +152,28 @@ public class ByteBuffer {
appendBytes(name.getByteArray(), name.getByteOffset(), name.getByteLength()); appendBytes(name.getByteArray(), name.getByteOffset(), name.getByteLength());
} }
/** Append the content of a given input stream, and then close the stream. /** Append the content of the given input stream.
*/ */
public void appendStream(InputStream is) throws IOException { public void appendStream(InputStream input) throws IOException {
try (InputStream input = is) { while (true) {
while (true) {
// Read another chunk of data, using size hint from available(). // Read another chunk of data, using size hint from available().
// If available() is accurate, the array size should be just right. // If available() is accurate, the array size should be just right.
int amountToRead = Math.max(input.available(), 64); int amountToRead = Math.max(input.available(), 64);
elems = ArrayUtils.ensureCapacity(elems, length + amountToRead); elems = ArrayUtils.ensureCapacity(elems, length + amountToRead);
int amountRead = input.read(elems, length, amountToRead); int amountRead = input.read(elems, length, amountToRead);
if (amountRead == -1) if (amountRead == -1)
break;
length += amountRead;
// Check for the common case where input.available() returned the
// entire remaining input; in that case, avoid an extra array extension.
// Note we are guaranteed that elems.length >= length + 1 at this point.
if (amountRead == amountToRead) {
int byt = input.read();
if (byt == -1)
break; break;
length += amountRead; elems[length++] = (byte)byt;
// Check for the common case where input.available() returned the
// entire remaining input; in that case, avoid an extra array extension.
// Note we are guaranteed that elems.length >= length + 1 at this point.
if (amountRead == amountToRead) {
int byt = input.read();
if (byt == -1)
break;
elems[length++] = (byte)byt;
}
} }
} }
} }
@ -292,6 +295,15 @@ public class ByteBuffer {
throw new UnderflowException(length); throw new UnderflowException(length);
} }
/** Create a {@link java.nio.ByteBuffer} view of this instance.
*
* <p>
* If this instance is modified, the returned buffer may no longer reflect it.
*/
public java.nio.ByteBuffer asByteBuffer() {
return java.nio.ByteBuffer.wrap(elems, 0, length);
}
// UnderflowException // UnderflowException
/** Thrown when trying to read past the end of the buffer. /** Thrown when trying to read past the end of the buffer.