@@ -187,6 +187,7 @@ public ClassReader(
187
187
int currentCpInfoIndex = 1 ;
188
188
int currentCpInfoOffset = classFileOffset + 10 ;
189
189
int currentMaxStringLength = 0 ;
190
+ boolean hasBootstrapMethods = false ;
190
191
// The offset of the other entries depend on the total size of all the previous entries.
191
192
while (currentCpInfoIndex < constantPoolCount ) {
192
193
cpInfoOffsets [currentCpInfoIndex ++] = currentCpInfoOffset + 1 ;
@@ -198,9 +199,12 @@ public ClassReader(
198
199
case Symbol .CONSTANT_INTEGER_TAG :
199
200
case Symbol .CONSTANT_FLOAT_TAG :
200
201
case Symbol .CONSTANT_NAME_AND_TYPE_TAG :
202
+ cpInfoSize = 5 ;
203
+ break ;
201
204
case Symbol .CONSTANT_INVOKE_DYNAMIC_TAG :
202
205
case Symbol .CONSTANT_DYNAMIC_TAG :
203
206
cpInfoSize = 5 ;
207
+ hasBootstrapMethods = true ;
204
208
break ;
205
209
case Symbol .CONSTANT_LONG_TAG :
206
210
case Symbol .CONSTANT_DOUBLE_TAG :
@@ -236,29 +240,8 @@ public ClassReader(
236
240
this .header = currentCpInfoOffset ;
237
241
238
242
// Read the BootstrapMethods attribute, if any (only get the offset of each method).
239
- int currentAttributeOffset = getFirstAttributeOffset ();
240
- int [] currentBootstrapMethodOffsets = null ;
241
- for (int i = readUnsignedShort (currentAttributeOffset - 2 ); i > 0 ; --i ) {
242
- // Read the attribute_info's attribute_name and attribute_length fields.
243
- String attributeName = readUTF8 (currentAttributeOffset , new char [maxStringLength ]);
244
- int attributeLength = readInt (currentAttributeOffset + 2 );
245
- currentAttributeOffset += 6 ;
246
- if (Constants .BOOTSTRAP_METHODS .equals (attributeName )) {
247
- // Read the num_bootstrap_methods field and create an array of this size.
248
- currentBootstrapMethodOffsets = new int [readUnsignedShort (currentAttributeOffset )];
249
- // Compute and store the offset of each 'bootstrap_methods' array field entry.
250
- int currentBootstrapMethodOffset = currentAttributeOffset + 2 ;
251
- for (int j = 0 ; j < currentBootstrapMethodOffsets .length ; ++j ) {
252
- currentBootstrapMethodOffsets [j ] = currentBootstrapMethodOffset ;
253
- // Skip the bootstrap_method_ref and num_bootstrap_arguments fields (2 bytes each),
254
- // as well as the bootstrap_arguments array field (of size num_bootstrap_arguments * 2).
255
- currentBootstrapMethodOffset +=
256
- 4 + readUnsignedShort (currentBootstrapMethodOffset + 2 ) * 2 ;
257
- }
258
- }
259
- currentAttributeOffset += attributeLength ;
260
- }
261
- this .bootstrapMethodOffsets = currentBootstrapMethodOffsets ;
243
+ this .bootstrapMethodOffsets =
244
+ hasBootstrapMethods ? readBootstrapMethodsAttribute (currentMaxStringLength ) : null ;
262
245
}
263
246
264
247
/**
@@ -345,7 +328,7 @@ public String getClassName() {
345
328
* Returns the internal of name of the super class (see {@link Type#getInternalName()}). For
346
329
* interfaces, the super class is {@link Object}.
347
330
*
348
- * @return the internal name of the super class, or <tt> null</tt> for {@link Object} class.
331
+ * @return the internal name of the super class, or {@literal null} for {@link Object} class.
349
332
* @see ClassVisitor#visit(int, int, String, String, String, String[])
350
333
*/
351
334
public String getSuperName () {
@@ -538,7 +521,7 @@ public void accept(
538
521
539
522
// Visit the NestHost attribute.
540
523
if (nestHostClass != null ) {
541
- classVisitor .visitNestHostExperimental (nestHostClass );
524
+ classVisitor .visitNestHost (nestHostClass );
542
525
}
543
526
544
527
// Visit the EnclosingMethod attribute.
@@ -648,7 +631,7 @@ public void accept(
648
631
int numberOfNestMembers = readUnsignedShort (nestMembersOffset );
649
632
int currentNestMemberOffset = nestMembersOffset + 2 ;
650
633
while (numberOfNestMembers -- > 0 ) {
651
- classVisitor .visitNestMemberExperimental (readClass (currentNestMemberOffset , charBuffer ));
634
+ classVisitor .visitNestMember (readClass (currentNestMemberOffset , charBuffer ));
652
635
currentNestMemberOffset += 2 ;
653
636
}
654
637
}
@@ -2775,7 +2758,7 @@ private int readElementValues(
2775
2758
* @param annotationVisitor the visitor that must visit the element_value structure.
2776
2759
* @param elementValueOffset the start offset in {@link #b} of the element_value structure to be
2777
2760
* read.
2778
- * @param elementName the name of the element_value structure to be read, or <tt> null</tt> .
2761
+ * @param elementName the name of the element_value structure to be read, or {@literal null} .
2779
2762
* @param charBuffer the buffer used to read strings in the constant pool.
2780
2763
* @return the end offset of the JVMS 'element_value' structure.
2781
2764
*/
@@ -3222,6 +3205,41 @@ final int getFirstAttributeOffset() {
3222
3205
return currentOffset + 2 ;
3223
3206
}
3224
3207
3208
+ /**
3209
+ * Reads the BootstrapMethods attribute to compute the offset of each bootstrap method.
3210
+ *
3211
+ * @param maxStringLength a conservative estimate of the maximum length of the strings contained
3212
+ * in the constant pool of the class.
3213
+ * @return the offsets of the bootstrap methods or null.
3214
+ */
3215
+ private int [] readBootstrapMethodsAttribute (final int maxStringLength ) {
3216
+ char [] charBuffer = new char [maxStringLength ];
3217
+ int currentAttributeOffset = getFirstAttributeOffset ();
3218
+ int [] currentBootstrapMethodOffsets = null ;
3219
+ for (int i = readUnsignedShort (currentAttributeOffset - 2 ); i > 0 ; --i ) {
3220
+ // Read the attribute_info's attribute_name and attribute_length fields.
3221
+ String attributeName = readUTF8 (currentAttributeOffset , charBuffer );
3222
+ int attributeLength = readInt (currentAttributeOffset + 2 );
3223
+ currentAttributeOffset += 6 ;
3224
+ if (Constants .BOOTSTRAP_METHODS .equals (attributeName )) {
3225
+ // Read the num_bootstrap_methods field and create an array of this size.
3226
+ currentBootstrapMethodOffsets = new int [readUnsignedShort (currentAttributeOffset )];
3227
+ // Compute and store the offset of each 'bootstrap_methods' array field entry.
3228
+ int currentBootstrapMethodOffset = currentAttributeOffset + 2 ;
3229
+ for (int j = 0 ; j < currentBootstrapMethodOffsets .length ; ++j ) {
3230
+ currentBootstrapMethodOffsets [j ] = currentBootstrapMethodOffset ;
3231
+ // Skip the bootstrap_method_ref and num_bootstrap_arguments fields (2 bytes each),
3232
+ // as well as the bootstrap_arguments array field (of size num_bootstrap_arguments * 2).
3233
+ currentBootstrapMethodOffset +=
3234
+ 4 + readUnsignedShort (currentBootstrapMethodOffset + 2 ) * 2 ;
3235
+ }
3236
+ return currentBootstrapMethodOffsets ;
3237
+ }
3238
+ currentAttributeOffset += attributeLength ;
3239
+ }
3240
+ return null ;
3241
+ }
3242
+
3225
3243
/**
3226
3244
* Reads a non standard JVMS 'attribute' structure in {@link #b}.
3227
3245
*
@@ -3236,8 +3254,8 @@ final int getFirstAttributeOffset() {
3236
3254
* @param codeAttributeOffset the start offset of the enclosing Code attribute in {@link #b}, or
3237
3255
* -1 if the attribute to be read is not a code attribute. The 6 attribute header bytes
3238
3256
* (attribute_name_index and attribute_length) are not taken into account here.
3239
- * @param labels the labels of the method's code, or <tt> null</tt> if the attribute to be read is
3240
- * not a code attribute.
3257
+ * @param labels the labels of the method's code, or {@literal null} if the attribute to be read
3258
+ * is not a code attribute.
3241
3259
* @return the attribute that has been read.
3242
3260
*/
3243
3261
private Attribute readAttribute (
0 commit comments