in asm/src/main/java/org/objectweb/asm/ClassReader.java [1551:1644]
private void readLocals(final MethodVisitor methodVisitor, final Context context, final int codeOffset) {
int currentOffset = codeOffset;
// Read the max_stack, max_locals and code_length fields.
final char[] charBuffer = context.charBuffer;
final int codeLength = readInt(currentOffset + 4);
currentOffset += 8;
if (codeLength > classFileBuffer.length - currentOffset) {
throw new IllegalArgumentException();
}
// Read the bytecode 'code' array to create a label for each referenced instruction.
final Label[] labels = context.currentMethodLabels = new Label[codeLength + 1];
currentOffset += codeLength;
int exceptionTableLength = readUnsignedShort(currentOffset);
currentOffset += 2 + 8 * exceptionTableLength;
// - The offset of the LocalVariableTable attribute, or 0.
int localVariableTableOffset = 0;
// - The offset of the LocalVariableTypeTable attribute, or 0.
int localVariableTypeTableOffset = 0;
int attributesCount = readUnsignedShort(currentOffset);
currentOffset += 2;
while (attributesCount-- > 0) {
// Read the attribute_info's attribute_name and attribute_length fields.
String attributeName = readUTF8(currentOffset, charBuffer);
int attributeLength = readInt(currentOffset + 2);
currentOffset += 6;
if (Constants.LOCAL_VARIABLE_TABLE.equals(attributeName)) {
if ((context.parsingOptions & SKIP_DEBUG) == 0) {
localVariableTableOffset = currentOffset;
// Parse the attribute to find the corresponding (debug only) labels.
int currentLocalVariableTableOffset = currentOffset;
int localVariableTableLength = readUnsignedShort(currentLocalVariableTableOffset);
currentLocalVariableTableOffset += 2;
while (localVariableTableLength-- > 0) {
int startPc = readUnsignedShort(currentLocalVariableTableOffset);
createDebugLabel(startPc, labels);
int length = readUnsignedShort(currentLocalVariableTableOffset + 2);
createDebugLabel(startPc + length, labels);
// Skip the name_index, descriptor_index and index fields (2 bytes each).
currentLocalVariableTableOffset += 10;
}
}
} else if (Constants.LOCAL_VARIABLE_TYPE_TABLE.equals(attributeName)) {
localVariableTypeTableOffset = currentOffset;
// Here we do not extract the labels corresponding to the attribute content. We assume they
// are the same or a subset of those of the LocalVariableTable attribute.
}
currentOffset += attributeLength;
}
// Visit LocalVariableTable and LocalVariableTypeTable attributes.
if (localVariableTableOffset != 0 && (context.parsingOptions & SKIP_DEBUG) == 0) {
// The (start_pc, index, signature_index) fields of each entry of the LocalVariableTypeTable.
int[] typeTable = null;
if (localVariableTypeTableOffset != 0) {
typeTable = new int[readUnsignedShort(localVariableTypeTableOffset) * 3];
currentOffset = localVariableTypeTableOffset + 2;
int typeTableIndex = typeTable.length;
while (typeTableIndex > 0) {
// Store the offset of 'signature_index', and the value of 'index' and 'start_pc'.
typeTable[--typeTableIndex] = currentOffset + 6;
typeTable[--typeTableIndex] = readUnsignedShort(currentOffset + 8);
typeTable[--typeTableIndex] = readUnsignedShort(currentOffset);
currentOffset += 10;
}
}
int localVariableTableLength = readUnsignedShort(localVariableTableOffset);
currentOffset = localVariableTableOffset + 2;
while (localVariableTableLength-- > 0) {
int startPc = readUnsignedShort(currentOffset);
int length = readUnsignedShort(currentOffset + 2);
String name = readUTF8(currentOffset + 4, charBuffer);
String descriptor = readUTF8(currentOffset + 6, charBuffer);
int index = readUnsignedShort(currentOffset + 8);
currentOffset += 10;
String signature = null;
if (typeTable != null) {
for (int i = 0; i < typeTable.length; i += 3) {
if (typeTable[i] == startPc && typeTable[i + 1] == index) {
signature = readUTF8(typeTable[i + 2], charBuffer);
break;
}
}
}
methodVisitor.visitLocalVariable(
name, descriptor, signature, labels[startPc], labels[startPc + length], index);
}
}
}