@@ -88,6 +88,9 @@ public class ClassReader {
88
88
*/
89
89
static final int EXPAND_ASM_INSNS = 256 ;
90
90
91
+ /** The maximum size of array to allocate. */
92
+ private static final int MAX_BUFFER_SIZE = 1024 * 1024 ;
93
+
91
94
/** The size of the temporary byte array used to read class input streams chunk by chunk. */
92
95
private static final int INPUT_STREAM_DATA_CHUNK_SIZE = 4096 ;
93
96
@@ -310,13 +313,19 @@ private static byte[] readStream(final InputStream inputStream, final boolean cl
310
313
if (inputStream == null ) {
311
314
throw new IOException ("Class not found" );
312
315
}
316
+ int bufferSize = calculateBufferSize (inputStream );
313
317
try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream ()) {
314
- byte [] data = new byte [INPUT_STREAM_DATA_CHUNK_SIZE ];
318
+ byte [] data = new byte [bufferSize ];
315
319
int bytesRead ;
316
- while ((bytesRead = inputStream .read (data , 0 , data .length )) != -1 ) {
320
+ int readCount = 0 ;
321
+ while ((bytesRead = inputStream .read (data , 0 , bufferSize )) != -1 ) {
317
322
outputStream .write (data , 0 , bytesRead );
323
+ readCount ++;
318
324
}
319
325
outputStream .flush ();
326
+ if (readCount == 1 ) {
327
+ return data ;
328
+ }
320
329
return outputStream .toByteArray ();
321
330
} finally {
322
331
if (close ) {
@@ -325,6 +334,20 @@ private static byte[] readStream(final InputStream inputStream, final boolean cl
325
334
}
326
335
}
327
336
337
+ private static int calculateBufferSize (final InputStream inputStream ) throws IOException {
338
+ int expectedLength = inputStream .available ();
339
+ /*
340
+ * Some implementations can return 0 while holding available data
341
+ * (e.g. new FileInputStream("/proc/a_file"))
342
+ * Also in some pathological cases a very small number might be returned,
343
+ * and in this case we use default size
344
+ */
345
+ if (expectedLength < 256 ) {
346
+ return INPUT_STREAM_DATA_CHUNK_SIZE ;
347
+ }
348
+ return Math .min (expectedLength , MAX_BUFFER_SIZE );
349
+ }
350
+
328
351
// -----------------------------------------------------------------------------------------------
329
352
// Accessors
330
353
// -----------------------------------------------------------------------------------------------
@@ -3456,25 +3479,24 @@ final int getFirstAttributeOffset() {
3456
3479
private int [] readBootstrapMethodsAttribute (final int maxStringLength ) {
3457
3480
char [] charBuffer = new char [maxStringLength ];
3458
3481
int currentAttributeOffset = getFirstAttributeOffset ();
3459
- int [] currentBootstrapMethodOffsets = null ;
3460
3482
for (int i = readUnsignedShort (currentAttributeOffset - 2 ); i > 0 ; --i ) {
3461
3483
// Read the attribute_info's attribute_name and attribute_length fields.
3462
3484
String attributeName = readUTF8 (currentAttributeOffset , charBuffer );
3463
3485
int attributeLength = readInt (currentAttributeOffset + 2 );
3464
3486
currentAttributeOffset += 6 ;
3465
3487
if (Constants .BOOTSTRAP_METHODS .equals (attributeName )) {
3466
3488
// Read the num_bootstrap_methods field and create an array of this size.
3467
- currentBootstrapMethodOffsets = new int [readUnsignedShort (currentAttributeOffset )];
3489
+ int [] result = new int [readUnsignedShort (currentAttributeOffset )];
3468
3490
// Compute and store the offset of each 'bootstrap_methods' array field entry.
3469
3491
int currentBootstrapMethodOffset = currentAttributeOffset + 2 ;
3470
- for (int j = 0 ; j < currentBootstrapMethodOffsets .length ; ++j ) {
3471
- currentBootstrapMethodOffsets [j ] = currentBootstrapMethodOffset ;
3492
+ for (int j = 0 ; j < result .length ; ++j ) {
3493
+ result [j ] = currentBootstrapMethodOffset ;
3472
3494
// Skip the bootstrap_method_ref and num_bootstrap_arguments fields (2 bytes each),
3473
3495
// as well as the bootstrap_arguments array field (of size num_bootstrap_arguments * 2).
3474
3496
currentBootstrapMethodOffset +=
3475
3497
4 + readUnsignedShort (currentBootstrapMethodOffset + 2 ) * 2 ;
3476
3498
}
3477
- return currentBootstrapMethodOffsets ;
3499
+ return result ;
3478
3500
}
3479
3501
currentAttributeOffset += attributeLength ;
3480
3502
}
0 commit comments