From 69e8bcdf401ececad932e9502b67ddeacfe2e36e Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Mon, 17 Sep 2018 19:09:07 +0200 Subject: [PATCH] Checkstyle updates from ASM master Issue: SPR-17267 --- .../org/springframework/asm/ByteVector.java | 13 +- .../org/springframework/asm/ClassReader.java | 76 ++-- .../asm/ClassTooLargeException.java | 12 +- .../org/springframework/asm/ClassWriter.java | 9 +- .../org/springframework/asm/Constants.java | 4 +- .../java/org/springframework/asm/Frame.java | 127 +++--- .../java/org/springframework/asm/Label.java | 2 +- .../asm/MethodTooLargeException.java | 24 +- .../springframework/asm/MethodVisitor.java | 18 +- .../org/springframework/asm/MethodWriter.java | 111 ++--- .../java/org/springframework/asm/Opcodes.java | 1 + .../java/org/springframework/asm/Symbol.java | 2 + .../org/springframework/asm/SymbolTable.java | 165 ++++--- .../java/org/springframework/asm/Type.java | 411 +++++++++--------- 14 files changed, 513 insertions(+), 462 deletions(-) diff --git a/spring-core/src/main/java/org/springframework/asm/ByteVector.java b/spring-core/src/main/java/org/springframework/asm/ByteVector.java index 17d21320243..3789eec3fd6 100644 --- a/spring-core/src/main/java/org/springframework/asm/ByteVector.java +++ b/spring-core/src/main/java/org/springframework/asm/ByteVector.java @@ -239,6 +239,7 @@ public class ByteVector { * @param stringValue a String whose UTF8 encoded length must be less than 65536. * @return this byte vector. */ + // DontCheck(AbbreviationAsWordInName): can't be renamed (for backward binary compatibility). public ByteVector putUTF8(final String stringValue) { int charLength = stringValue.length(); if (charLength > 65535) { @@ -261,7 +262,7 @@ public class ByteVector { currentData[currentLength++] = (byte) charValue; } else { length = currentLength; - return encodeUTF8(stringValue, i, 65535); + return encodeUtf8(stringValue, i, 65535); } } length = currentLength; @@ -280,14 +281,14 @@ public class ByteVector { * encoded characters. * @return this byte vector. */ - final ByteVector encodeUTF8(final String stringValue, final int offset, final int maxByteLength) { + final ByteVector encodeUtf8(final String stringValue, final int offset, final int maxByteLength) { int charLength = stringValue.length(); int byteLength = offset; for (int i = offset; i < charLength; ++i) { char charValue = stringValue.charAt(i); - if (charValue >= '\u0001' && charValue <= '\u007F') { + if (charValue >= 0x0001 && charValue <= 0x007F) { byteLength++; - } else if (charValue <= '\u07FF') { + } else if (charValue <= 0x07FF) { byteLength += 2; } else { byteLength += 3; @@ -308,9 +309,9 @@ public class ByteVector { int currentLength = length; for (int i = offset; i < charLength; ++i) { char charValue = stringValue.charAt(i); - if (charValue >= '\u0001' && charValue <= '\u007F') { + if (charValue >= 0x0001 && charValue <= 0x007F) { data[currentLength++] = (byte) charValue; - } else if (charValue <= '\u07FF') { + } else if (charValue <= 0x07FF) { data[currentLength++] = (byte) (0xC0 | charValue >> 6 & 0x1F); data[currentLength++] = (byte) (0x80 | charValue & 0x3F); } else { diff --git a/spring-core/src/main/java/org/springframework/asm/ClassReader.java b/spring-core/src/main/java/org/springframework/asm/ClassReader.java index ea5530f616d..6c355c65b7a 100644 --- a/spring-core/src/main/java/org/springframework/asm/ClassReader.java +++ b/spring-core/src/main/java/org/springframework/asm/ClassReader.java @@ -99,6 +99,7 @@ public class ClassReader { * necessarily start at offset 0. Use {@link #getItem} and {@link #header} to get correct * ClassFile element offsets within this byte array. */ + // DontCheck(MemberName): can't be renamed (for backward binary compatibility). public final byte[] b; /** @@ -488,7 +489,7 @@ public class ClassReader { accessFlags |= Opcodes.ACC_SYNTHETIC; } else if (Constants.SOURCE_DEBUG_EXTENSION.equals(attributeName)) { sourceDebugExtension = - readUTF(currentAttributeOffset, attributeLength, new char[attributeLength]); + readUtf(currentAttributeOffset, attributeLength, new char[attributeLength]); } else if (Constants.RUNTIME_INVISIBLE_ANNOTATIONS.equals(attributeName)) { runtimeInvisibleAnnotationsOffset = currentAttributeOffset; } else if (Constants.RUNTIME_INVISIBLE_TYPE_ANNOTATIONS.equals(attributeName)) { @@ -530,7 +531,8 @@ public class ClassReader { // Visit the Module, ModulePackages and ModuleMainClass attributes. if (moduleOffset != 0) { - readModule(classVisitor, context, moduleOffset, modulePackagesOffset, moduleMainClass); + readModuleAttributes( + classVisitor, context, moduleOffset, modulePackagesOffset, moduleMainClass); } // Visit the NestHost attribute. @@ -685,7 +687,7 @@ public class ClassReader { // ---------------------------------------------------------------------------------------------- /** - * Reads the module attribute and visit it. + * Reads the Module, ModulePackages and ModuleMainClass attributes and visit them. * * @param classVisitor the current class visitor * @param context information about the class being parsed. @@ -695,7 +697,7 @@ public class ClassReader { * attribute_info's attribute_name_index and attribute_length fields), or 0. * @param moduleMainClass the string corresponding to the ModuleMainClass attribute, or null. */ - private void readModule( + private void readModuleAttributes( final ClassVisitor classVisitor, final Context context, final int moduleOffset, @@ -1111,7 +1113,7 @@ public class ClassReader { context.currentMethodAccessFlags, context.currentMethodName, context.currentMethodDescriptor, - signatureIndex == 0 ? null : readUTF(signatureIndex, charBuffer), + signatureIndex == 0 ? null : readUtf(signatureIndex, charBuffer), exceptions); if (methodVisitor == null) { return currentOffset; @@ -1601,18 +1603,15 @@ public class ClassReader { // Read the 'exception_table_length' and 'exception_table' field to create a label for each // referenced instruction, and to make methodVisitor visit the corresponding try catch blocks. - { - int exceptionTableLength = readUnsignedShort(currentOffset); - currentOffset += 2; - while (exceptionTableLength-- > 0) { - Label start = createLabel(readUnsignedShort(currentOffset), labels); - Label end = createLabel(readUnsignedShort(currentOffset + 2), labels); - Label handler = createLabel(readUnsignedShort(currentOffset + 4), labels); - String catchType = - readUTF8(cpInfoOffsets[readUnsignedShort(currentOffset + 6)], charBuffer); - currentOffset += 8; - methodVisitor.visitTryCatchBlock(start, end, handler, catchType); - } + int exceptionTableLength = readUnsignedShort(currentOffset); + currentOffset += 2; + while (exceptionTableLength-- > 0) { + Label start = createLabel(readUnsignedShort(currentOffset), labels); + Label end = createLabel(readUnsignedShort(currentOffset + 2), labels); + Label handler = createLabel(readUnsignedShort(currentOffset + 4), labels); + String catchType = readUTF8(cpInfoOffsets[readUnsignedShort(currentOffset + 6)], charBuffer); + currentOffset += 8; + methodVisitor.visitTryCatchBlock(start, end, handler, catchType); } // Read the Code attributes to create a label for each referenced instruction (the variables @@ -2142,11 +2141,11 @@ public class ClassReader { currentOffset += 4 - (currentBytecodeOffset & 3); // Read the instruction. Label defaultLabel = labels[currentBytecodeOffset + readInt(currentOffset)]; - int nPairs = readInt(currentOffset + 4); + int numPairs = readInt(currentOffset + 4); currentOffset += 8; - int[] keys = new int[nPairs]; - Label[] values = new Label[nPairs]; - for (int i = 0; i < nPairs; ++i) { + int[] keys = new int[numPairs]; + Label[] values = new Label[numPairs]; + for (int i = 0; i < numPairs; ++i) { keys[i] = readInt(currentOffset); values[i] = labels[currentBytecodeOffset + readInt(currentOffset + 4)]; currentOffset += 8; @@ -2958,12 +2957,12 @@ public class ClassReader { private void computeImplicitFrame(final Context context) { String methodDescriptor = context.currentMethodDescriptor; Object[] locals = context.currentFrameLocalTypes; - int nLocal = 0; + int numLocal = 0; if ((context.currentMethodAccessFlags & Opcodes.ACC_STATIC) == 0) { if ("".equals(context.currentMethodName)) { - locals[nLocal++] = Opcodes.UNINITIALIZED_THIS; + locals[numLocal++] = Opcodes.UNINITIALIZED_THIS; } else { - locals[nLocal++] = readClass(header + 2, context.charBuffer); + locals[numLocal++] = readClass(header + 2, context.charBuffer); } } // Parse the method descriptor, one argument type descriptor at each iteration. Start by @@ -2977,16 +2976,16 @@ public class ClassReader { case 'B': case 'S': case 'I': - locals[nLocal++] = Opcodes.INTEGER; + locals[numLocal++] = Opcodes.INTEGER; break; case 'F': - locals[nLocal++] = Opcodes.FLOAT; + locals[numLocal++] = Opcodes.FLOAT; break; case 'J': - locals[nLocal++] = Opcodes.LONG; + locals[numLocal++] = Opcodes.LONG; break; case 'D': - locals[nLocal++] = Opcodes.DOUBLE; + locals[numLocal++] = Opcodes.DOUBLE; break; case '[': while (methodDescriptor.charAt(currentMethodDescritorOffset) == '[') { @@ -2998,7 +2997,7 @@ public class ClassReader { ++currentMethodDescritorOffset; } } - locals[nLocal++] = + locals[numLocal++] = methodDescriptor.substring( currentArgumentDescriptorStartOffset, ++currentMethodDescritorOffset); break; @@ -3006,12 +3005,12 @@ public class ClassReader { while (methodDescriptor.charAt(currentMethodDescritorOffset) != ';') { ++currentMethodDescritorOffset; } - locals[nLocal++] = + locals[numLocal++] = methodDescriptor.substring( currentArgumentDescriptorStartOffset + 1, currentMethodDescritorOffset++); break; default: - context.currentFrameLocalCount = nLocal; + context.currentFrameLocalCount = numLocal; return; } } @@ -3178,7 +3177,11 @@ public class ClassReader { // Methods to parse attributes // ---------------------------------------------------------------------------------------------- - /** @return the offset in {@link #b} of the first ClassFile's 'attributes' array field entry. */ + /** + * Returns the offset in {@link #b} of the first ClassFile's 'attributes' array field entry. + * + * @return the offset in {@link #b} of the first ClassFile's 'attributes' array field entry. + */ final int getFirstAttributeOffset() { // Skip the access_flags, this_class, super_class, and interfaces_count fields (using 2 bytes // each), as well as the interfaces array field (2 bytes per interface). @@ -3399,12 +3402,13 @@ public class ClassReader { * large. It is not automatically resized. * @return the String corresponding to the specified CONSTANT_Utf8 entry. */ + // DontCheck(AbbreviationAsWordInName): can't be renamed (for backward binary compatibility). public String readUTF8(final int offset, final char[] charBuffer) { int constantPoolEntryIndex = readUnsignedShort(offset); if (offset == 0 || constantPoolEntryIndex == 0) { return null; } - return readUTF(constantPoolEntryIndex, charBuffer); + return readUtf(constantPoolEntryIndex, charBuffer); } /** @@ -3416,14 +3420,14 @@ public class ClassReader { * large. It is not automatically resized. * @return the String corresponding to the specified CONSTANT_Utf8 entry. */ - final String readUTF(final int constantPoolEntryIndex, final char[] charBuffer) { + final String readUtf(final int constantPoolEntryIndex, final char[] charBuffer) { String value = constantUtf8Values[constantPoolEntryIndex]; if (value != null) { return value; } int cpInfoOffset = cpInfoOffsets[constantPoolEntryIndex]; return constantUtf8Values[constantPoolEntryIndex] = - readUTF(cpInfoOffset + 2, readUnsignedShort(cpInfoOffset), charBuffer); + readUtf(cpInfoOffset + 2, readUnsignedShort(cpInfoOffset), charBuffer); } /** @@ -3435,7 +3439,7 @@ public class ClassReader { * large. It is not automatically resized. * @return the String corresponding to the specified UTF8 string. */ - private String readUTF(final int utfOffset, final int utfLength, final char[] charBuffer) { + private String readUtf(final int utfOffset, final int utfLength, final char[] charBuffer) { int currentOffset = utfOffset; int endOffset = currentOffset + utfLength; int strLength = 0; diff --git a/spring-core/src/main/java/org/springframework/asm/ClassTooLargeException.java b/spring-core/src/main/java/org/springframework/asm/ClassTooLargeException.java index a5aea999cf0..aeb16be9c6c 100644 --- a/spring-core/src/main/java/org/springframework/asm/ClassTooLargeException.java +++ b/spring-core/src/main/java/org/springframework/asm/ClassTooLargeException.java @@ -51,12 +51,20 @@ public final class ClassTooLargeException extends IndexOutOfBoundsException { this.constantPoolCount = constantPoolCount; } - /** @return the internal name of the class. */ + /** + * Returns the internal name of the class. + * + * @return the internal name of the class. + */ public String getClassName() { return className; } - /** @return the number of constant pool items of the class. */ + /** + * Returns the number of constant pool items of the class. + * + * @return the number of constant pool items of the class. + */ public int getConstantPoolCount() { return constantPoolCount; } diff --git a/spring-core/src/main/java/org/springframework/asm/ClassWriter.java b/spring-core/src/main/java/org/springframework/asm/ClassWriter.java index 4954f4f6f28..1bf78de2d3f 100644 --- a/spring-core/src/main/java/org/springframework/asm/ClassWriter.java +++ b/spring-core/src/main/java/org/springframework/asm/ClassWriter.java @@ -282,7 +282,7 @@ public class ClassWriter extends ClassVisitor { sourceFileIndex = symbolTable.addConstantUtf8(file); } if (debug != null) { - debugExtension = new ByteVector().encodeUTF8(debug, 0, Integer.MAX_VALUE); + debugExtension = new ByteVector().encodeUtf8(debug, 0, Integer.MAX_VALUE); } } @@ -674,7 +674,7 @@ public class ClassWriter extends ClassVisitor { * ones. */ private byte[] replaceAsmInstructions(final byte[] classFile, final boolean hasFrames) { - Attribute[] attributes = getAttributePrototypes(); + final Attribute[] attributes = getAttributePrototypes(); firstField = null; lastField = null; firstMethod = null; @@ -743,6 +743,7 @@ public class ClassWriter extends ClassVisitor { * @param value the String value. * @return the index of a new or already existing UTF8 item. */ + // DontCheck(AbbreviationAsWordInName): can't be renamed (for backward binary compatibility). public int newUTF8(final String value) { return symbolTable.addConstantUtf8(value); } @@ -947,13 +948,13 @@ public class ClassWriter extends ClassVisitor { Class class1; try { class1 = Class.forName(type1.replace('/', '.'), false, classLoader); - } catch (Exception e) { + } catch (ClassNotFoundException e) { throw new TypeNotPresentException(type1, e); } Class class2; try { class2 = Class.forName(type2.replace('/', '.'), false, classLoader); - } catch (Exception e) { + } catch (ClassNotFoundException e) { throw new TypeNotPresentException(type2, e); } if (class1.isAssignableFrom(class2)) { diff --git a/spring-core/src/main/java/org/springframework/asm/Constants.java b/spring-core/src/main/java/org/springframework/asm/Constants.java index f19da4764f1..4713f09e5fe 100644 --- a/spring-core/src/main/java/org/springframework/asm/Constants.java +++ b/spring-core/src/main/java/org/springframework/asm/Constants.java @@ -36,8 +36,6 @@ package org.springframework.asm; */ final class Constants implements Opcodes { - private Constants() {} - // The ClassFile attribute names, in the order they are defined in // https://docs.oracle.com/javase/specs/jvms/se11/html/jvms-4.html#jvms-4.7-300. @@ -173,4 +171,6 @@ final class Constants implements Opcodes { static final int ASM_IFNULL = IFNULL + ASM_IFNULL_OPCODE_DELTA; static final int ASM_IFNONNULL = IFNONNULL + ASM_IFNULL_OPCODE_DELTA; static final int ASM_GOTO_W = 220; + + private Constants() {} } diff --git a/spring-core/src/main/java/org/springframework/asm/Frame.java b/spring-core/src/main/java/org/springframework/asm/Frame.java index 939e229893c..80e9351ef4d 100644 --- a/spring-core/src/main/java/org/springframework/asm/Frame.java +++ b/spring-core/src/main/java/org/springframework/asm/Frame.java @@ -223,6 +223,38 @@ class Frame { */ private int[] initializations; + // ----------------------------------------------------------------------------------------------- + // Constructor + // ----------------------------------------------------------------------------------------------- + + /** + * Constructs a new Frame. + * + * @param owner the basic block to which these input and output stack map frames correspond. + */ + Frame(final Label owner) { + this.owner = owner; + } + + /** + * Sets this frame to the value of the given frame. + * + *

WARNING: after this method is called the two frames share the same data structures. It is + * recommended to discard the given frame to avoid unexpected side effects. + * + * @param frame The new frame value. + */ + final void copyFrom(final Frame frame) { + inputLocals = frame.inputLocals; + inputStack = frame.inputStack; + outputStackStart = 0; + outputLocals = frame.outputLocals; + outputStack = frame.outputStack; + outputStackTop = frame.outputStackTop; + initializationCount = frame.initializationCount; + initializations = frame.initializations; + } + // ----------------------------------------------------------------------------------------------- // Static methods to get abstract types from other type formats // ----------------------------------------------------------------------------------------------- @@ -336,38 +368,6 @@ class Frame { } } - // ----------------------------------------------------------------------------------------------- - // Constructor - // ----------------------------------------------------------------------------------------------- - - /** - * Constructs a new Frame. - * - * @param owner the basic block to which these input and output stack map frames correspond. - */ - Frame(final Label owner) { - this.owner = owner; - } - - /** - * Sets this frame to the value of the given frame. - * - *

WARNING: after this method is called the two frames share the same data structures. It is - * recommended to discard the given frame to avoid unexpected side effects. - * - * @param frame The new frame value. - */ - final void copyFrom(final Frame frame) { - inputLocals = frame.inputLocals; - inputStack = frame.inputStack; - outputStackStart = 0; - outputLocals = frame.outputLocals; - outputStack = frame.outputStack; - outputStackTop = frame.outputStackTop; - initializationCount = frame.initializationCount; - initializations = frame.initializations; - } - // ----------------------------------------------------------------------------------------------- // Methods related to the input frame // ----------------------------------------------------------------------------------------------- @@ -415,21 +415,21 @@ class Frame { * Sets the input frame from the given public API frame description. * * @param symbolTable the type table to use to lookup and store type {@link Symbol}. - * @param nLocal the number of local variables. + * @param numLocal the number of local variables. * @param local the local variable types, described using the same format as in {@link * MethodVisitor#visitFrame}. - * @param nStack the number of operand stack elements. + * @param numStack the number of operand stack elements. * @param stack the operand stack types, described using the same format as in {@link * MethodVisitor#visitFrame}. */ final void setInputFrameFromApiFormat( final SymbolTable symbolTable, - final int nLocal, + final int numLocal, final Object[] local, - final int nStack, + final int numStack, final Object[] stack) { int inputLocalIndex = 0; - for (int i = 0; i < nLocal; ++i) { + for (int i = 0; i < numLocal; ++i) { inputLocals[inputLocalIndex++] = getAbstractTypeFromApiFormat(symbolTable, local[i]); if (local[i] == Opcodes.LONG || local[i] == Opcodes.DOUBLE) { inputLocals[inputLocalIndex++] = TOP; @@ -438,15 +438,15 @@ class Frame { while (inputLocalIndex < inputLocals.length) { inputLocals[inputLocalIndex++] = TOP; } - int nStackTop = 0; - for (int i = 0; i < nStack; ++i) { + int numStackTop = 0; + for (int i = 0; i < numStack; ++i) { if (stack[i] == Opcodes.LONG || stack[i] == Opcodes.DOUBLE) { - ++nStackTop; + ++numStackTop; } } - inputStack = new int[nStack + nStackTop]; + inputStack = new int[numStack + numStackTop]; int inputStackIndex = 0; - for (int i = 0; i < nStack; ++i) { + for (int i = 0; i < numStack; ++i) { inputStack[inputStackIndex++] = getAbstractTypeFromApiFormat(symbolTable, stack[i]); if (stack[i] == Opcodes.LONG || stack[i] == Opcodes.DOUBLE) { inputStack[inputStackIndex++] = TOP; @@ -1122,13 +1122,13 @@ class Frame { // Compute the concrete types of the local variables at the end of the basic block corresponding // to this frame, by resolving its abstract output types, and merge these concrete types with // those of the local variables in the input frame of dstFrame. - int nLocal = inputLocals.length; - int nStack = inputStack.length; + int numLocal = inputLocals.length; + int numStack = inputStack.length; if (dstFrame.inputLocals == null) { - dstFrame.inputLocals = new int[nLocal]; + dstFrame.inputLocals = new int[numLocal]; frameChanged = true; } - for (int i = 0; i < nLocal; ++i) { + for (int i = 0; i < numLocal; ++i) { int concreteOutputType; if (outputLocals != null && i < outputLocals.length) { int abstractOutputType = outputLocals[i]; @@ -1152,7 +1152,7 @@ class Frame { // By definition, a STACK_KIND type designates the concrete type of a local variable at // the beginning of the basic block corresponding to this frame (which is known when // this method is called, but was not when the abstract type was computed). - concreteOutputType = dim + inputStack[nStack - (abstractOutputType & VALUE_MASK)]; + concreteOutputType = dim + inputStack[numStack - (abstractOutputType & VALUE_MASK)]; if ((abstractOutputType & TOP_IF_LONG_OR_DOUBLE_FLAG) != 0 && (concreteOutputType == LONG || concreteOutputType == DOUBLE)) { concreteOutputType = TOP; @@ -1181,7 +1181,7 @@ class Frame { // frame (and the input stack of dstFrame should be compatible, i.e. merged, with a one // element stack containing the caught exception type). if (catchTypeIndex > 0) { - for (int i = 0; i < nLocal; ++i) { + for (int i = 0; i < numLocal; ++i) { frameChanged |= merge(symbolTable, inputLocals[i], dstFrame.inputLocals, i); } if (dstFrame.inputStack == null) { @@ -1195,15 +1195,15 @@ class Frame { // Compute the concrete types of the stack operands at the end of the basic block corresponding // to this frame, by resolving its abstract output types, and merge these concrete types with // those of the stack operands in the input frame of dstFrame. - int nInputStack = inputStack.length + outputStackStart; + int numInputStack = inputStack.length + outputStackStart; if (dstFrame.inputStack == null) { - dstFrame.inputStack = new int[nInputStack + outputStackTop]; + dstFrame.inputStack = new int[numInputStack + outputStackTop]; frameChanged = true; } // First, do this for the stack operands that have not been popped in the basic block // corresponding to this frame, and which are therefore equal to their value in the input // frame (except for uninitialized types, which may have been initialized). - for (int i = 0; i < nInputStack; ++i) { + for (int i = 0; i < numInputStack; ++i) { int concreteOutputType = inputStack[i]; if (initializations != null) { concreteOutputType = getInitializedType(symbolTable, concreteOutputType); @@ -1224,7 +1224,7 @@ class Frame { concreteOutputType = TOP; } } else if (kind == STACK_KIND) { - concreteOutputType = dim + inputStack[nStack - (abstractOutputType & VALUE_MASK)]; + concreteOutputType = dim + inputStack[numStack - (abstractOutputType & VALUE_MASK)]; if ((abstractOutputType & TOP_IF_LONG_OR_DOUBLE_FLAG) != 0 && (concreteOutputType == LONG || concreteOutputType == DOUBLE)) { concreteOutputType = TOP; @@ -1235,7 +1235,8 @@ class Frame { if (initializations != null) { concreteOutputType = getInitializedType(symbolTable, concreteOutputType); } - frameChanged |= merge(symbolTable, concreteOutputType, dstFrame.inputStack, nInputStack + i); + frameChanged |= + merge(symbolTable, concreteOutputType, dstFrame.inputStack, numInputStack + i); } return frameChanged; } @@ -1348,38 +1349,38 @@ class Frame { // Compute the number of locals, ignoring TOP types that are just after a LONG or a DOUBLE, and // all trailing TOP types. int[] localTypes = inputLocals; - int nLocal = 0; - int nTrailingTop = 0; + int numLocal = 0; + int numTrailingTop = 0; int i = 0; while (i < localTypes.length) { int localType = localTypes[i]; i += (localType == LONG || localType == DOUBLE) ? 2 : 1; if (localType == TOP) { - nTrailingTop++; + numTrailingTop++; } else { - nLocal += nTrailingTop + 1; - nTrailingTop = 0; + numLocal += numTrailingTop + 1; + numTrailingTop = 0; } } // Compute the stack size, ignoring TOP types that are just after a LONG or a DOUBLE. int[] stackTypes = inputStack; - int nStack = 0; + int numStack = 0; i = 0; while (i < stackTypes.length) { int stackType = stackTypes[i]; i += (stackType == LONG || stackType == DOUBLE) ? 2 : 1; - nStack++; + numStack++; } // Visit the frame and its content. - int frameIndex = methodWriter.visitFrameStart(owner.bytecodeOffset, nLocal, nStack); + int frameIndex = methodWriter.visitFrameStart(owner.bytecodeOffset, numLocal, numStack); i = 0; - while (nLocal-- > 0) { + while (numLocal-- > 0) { int localType = localTypes[i]; i += (localType == LONG || localType == DOUBLE) ? 2 : 1; methodWriter.visitAbstractType(frameIndex++, localType); } i = 0; - while (nStack-- > 0) { + while (numStack-- > 0) { int stackType = stackTypes[i]; i += (stackType == LONG || stackType == DOUBLE) ? 2 : 1; methodWriter.visitAbstractType(frameIndex++, stackType); diff --git a/spring-core/src/main/java/org/springframework/asm/Label.java b/spring-core/src/main/java/org/springframework/asm/Label.java index e34288bf845..0004179aa34 100644 --- a/spring-core/src/main/java/org/springframework/asm/Label.java +++ b/spring-core/src/main/java/org/springframework/asm/Label.java @@ -178,7 +178,7 @@ public class Label { * and {@link #FORWARD_REFERENCE_HANDLE_MASK}. * * - * For instance, for an ifnull instruction at bytecode offset x, 'sourceInsnBytecodeOffset' is + *

For instance, for an ifnull instruction at bytecode offset x, 'sourceInsnBytecodeOffset' is * equal to x, and 'reference' is of type {@link #FORWARD_REFERENCE_TYPE_SHORT} with value x + 1 * (because the ifnull instruction uses a 2 bytes bytecode offset operand stored one byte after * the start of the instruction itself). For the default case of a lookupswitch instruction at diff --git a/spring-core/src/main/java/org/springframework/asm/MethodTooLargeException.java b/spring-core/src/main/java/org/springframework/asm/MethodTooLargeException.java index 1f4164174f6..9095c62a4ee 100644 --- a/spring-core/src/main/java/org/springframework/asm/MethodTooLargeException.java +++ b/spring-core/src/main/java/org/springframework/asm/MethodTooLargeException.java @@ -61,22 +61,38 @@ public final class MethodTooLargeException extends IndexOutOfBoundsException { this.codeSize = codeSize; } - /** @return the internal name of the owner class. */ + /** + * Returns the internal name of the owner class. + * + * @return the internal name of the owner class. + */ public String getClassName() { return className; } - /** @return the name of the method. */ + /** + * Returns the name of the method. + * + * @return the name of the method. + */ public String getMethodName() { return methodName; } - /** @return the descriptor of the method. */ + /** + * Returns the descriptor of the method. + * + * @return the descriptor of the method. + */ public String getDescriptor() { return descriptor; } - /** @return the size of the method's Code attribute, in bytes. */ + /** + * Returns the size of the method's Code attribute, in bytes. + * + * @return the size of the method's Code attribute, in bytes. + */ public int getCodeSize() { return codeSize; } diff --git a/spring-core/src/main/java/org/springframework/asm/MethodVisitor.java b/spring-core/src/main/java/org/springframework/asm/MethodVisitor.java index 22617911659..5c404ac68f8 100644 --- a/spring-core/src/main/java/org/springframework/asm/MethodVisitor.java +++ b/spring-core/src/main/java/org/springframework/asm/MethodVisitor.java @@ -243,15 +243,15 @@ public abstract class MethodVisitor { *

  • {@link Opcodes#F_SAME} representing frame with exactly the same locals as the * previous frame and with the empty stack. *
  • {@link Opcodes#F_SAME1} representing frame with exactly the same locals as the - * previous frame and with single value on the stack ( nStack is 1 and + * previous frame and with single value on the stack ( numStack is 1 and * stack[0] contains value for the type of the stack item). *
  • {@link Opcodes#F_APPEND} representing frame with current locals are the same as the * locals in the previous frame, except that additional locals are defined ( - * nLocal is 1, 2 or 3 and local elements contains values + * numLocal is 1, 2 or 3 and local elements contains values * representing added types). *
  • {@link Opcodes#F_CHOP} representing frame with current locals are the same as the * locals in the previous frame, except that the last 1-3 locals are absent and with - * the empty stack (nLocals is 1, 2 or 3). + * the empty stack (numLocal is 1, 2 or 3). *
  • {@link Opcodes#F_FULL} representing complete frame data. * * @@ -264,7 +264,7 @@ public abstract class MethodVisitor { * @param type the type of this stack map frame. Must be {@link Opcodes#F_NEW} for expanded * frames, or {@link Opcodes#F_FULL}, {@link Opcodes#F_APPEND}, {@link Opcodes#F_CHOP}, {@link * Opcodes#F_SAME} or {@link Opcodes#F_APPEND}, {@link Opcodes#F_SAME1} for compressed frames. - * @param nLocal the number of local variables in the visited frame. + * @param numLocal the number of local variables in the visited frame. * @param local the local variable types in this frame. This array must not be modified. Primitive * types are represented by {@link Opcodes#TOP}, {@link Opcodes#INTEGER}, {@link * Opcodes#FLOAT}, {@link Opcodes#LONG}, {@link Opcodes#DOUBLE}, {@link Opcodes#NULL} or @@ -272,7 +272,7 @@ public abstract class MethodVisitor { * Reference types are represented by String objects (representing internal names), and * uninitialized types by Label objects (this label designates the NEW instruction that * created this uninitialized value). - * @param nStack the number of operand stack elements in the visited frame. + * @param numStack the number of operand stack elements in the visited frame. * @param stack the operand stack types in this frame. This array must not be modified. Its * content has the same format as the "local" array. * @throws IllegalStateException if a frame is visited just after another one, without any @@ -281,12 +281,12 @@ public abstract class MethodVisitor { */ public void visitFrame( final int type, - final int nLocal, + final int numLocal, final Object[] local, - final int nStack, + final int numStack, final Object[] stack) { if (mv != null) { - mv.visitFrame(type, nLocal, local, nStack, stack); + mv.visitFrame(type, numLocal, local, numStack, stack); } } @@ -390,7 +390,7 @@ public abstract class MethodVisitor { * Type#getInternalName()}). * @param name the method's name. * @param descriptor the method's descriptor (see {@link Type}). - * @deprecated + * @deprecated use {@link #visitMethodInsn(int, String, String, String, boolean)} instead. */ @Deprecated public void visitMethodInsn( diff --git a/spring-core/src/main/java/org/springframework/asm/MethodWriter.java b/spring-core/src/main/java/org/springframework/asm/MethodWriter.java index e6b8adaff8f..d2b844c5c70 100644 --- a/spring-core/src/main/java/org/springframework/asm/MethodWriter.java +++ b/spring-core/src/main/java/org/springframework/asm/MethodWriter.java @@ -531,11 +531,10 @@ final class MethodWriter extends MethodVisitor { * The current stack map frame. The first element contains the bytecode offset of the instruction * to which the frame corresponds, the second element is the number of locals and the third one is * the number of stack elements. The local variables start at index 3 and are followed by the - * operand stack elements. In summary frame[0] = offset, frame[1] = nLocal, frame[2] = nStack, - * frame[3] = nLocal. Local variables and operand stack entries contain abstract types, as defined - * in {@link Frame}, but restricted to {@link Frame#CONSTANT_KIND}, {@link Frame#REFERENCE_KIND} - * or {@link Frame#UNINITIALIZED_KIND} abstract types. Long and double types use only one array - * entry. + * operand stack elements. In summary frame[0] = offset, frame[1] = numLocal, frame[2] = numStack. + * Local variables and operand stack entries contain abstract types, as defined in {@link Frame}, + * but restricted to {@link Frame#CONSTANT_KIND}, {@link Frame#REFERENCE_KIND} or {@link + * Frame#UNINITIALIZED_KIND} abstract types. Long and double types use only one array entry. */ private int[] currentFrame; @@ -745,9 +744,9 @@ final class MethodWriter extends MethodVisitor { @Override public void visitFrame( final int type, - final int nLocal, + final int numLocal, final Object[] local, - final int nStack, + final int numStack, final Object[] stack) { if (compute == COMPUTE_ALL_FRAMES) { return; @@ -760,12 +759,12 @@ final class MethodWriter extends MethodVisitor { // can't be set if EXPAND_ASM_INSNS is not used). currentBasicBlock.frame = new CurrentFrame(currentBasicBlock); currentBasicBlock.frame.setInputFrameFromDescriptor( - symbolTable, accessFlags, descriptor, nLocal); + symbolTable, accessFlags, descriptor, numLocal); currentBasicBlock.frame.accept(this); } else { if (type == Opcodes.F_NEW) { currentBasicBlock.frame.setInputFrameFromApiFormat( - symbolTable, nLocal, local, nStack, stack); + symbolTable, numLocal, local, numStack, stack); } else { // In this case type is equal to F_INSERT by hypothesis, and currentBlock.frame contains // the stack map frame at the current instruction, computed from the last F_NEW frame @@ -781,12 +780,12 @@ final class MethodWriter extends MethodVisitor { symbolTable, accessFlags, descriptor, argumentsSize); implicitFirstFrame.accept(this); } - currentLocals = nLocal; - int frameIndex = visitFrameStart(code.length, nLocal, nStack); - for (int i = 0; i < nLocal; ++i) { + currentLocals = numLocal; + int frameIndex = visitFrameStart(code.length, numLocal, numStack); + for (int i = 0; i < numLocal; ++i) { currentFrame[frameIndex++] = Frame.getAbstractTypeFromApiFormat(symbolTable, local[i]); } - for (int i = 0; i < nStack; ++i) { + for (int i = 0; i < numStack; ++i) { currentFrame[frameIndex++] = Frame.getAbstractTypeFromApiFormat(symbolTable, stack[i]); } visitFrameEnd(); @@ -808,26 +807,26 @@ final class MethodWriter extends MethodVisitor { switch (type) { case Opcodes.F_FULL: - currentLocals = nLocal; - stackMapTableEntries.putByte(Frame.FULL_FRAME).putShort(offsetDelta).putShort(nLocal); - for (int i = 0; i < nLocal; ++i) { + currentLocals = numLocal; + stackMapTableEntries.putByte(Frame.FULL_FRAME).putShort(offsetDelta).putShort(numLocal); + for (int i = 0; i < numLocal; ++i) { putFrameType(local[i]); } - stackMapTableEntries.putShort(nStack); - for (int i = 0; i < nStack; ++i) { + stackMapTableEntries.putShort(numStack); + for (int i = 0; i < numStack; ++i) { putFrameType(stack[i]); } break; case Opcodes.F_APPEND: - currentLocals += nLocal; - stackMapTableEntries.putByte(Frame.SAME_FRAME_EXTENDED + nLocal).putShort(offsetDelta); - for (int i = 0; i < nLocal; ++i) { + currentLocals += numLocal; + stackMapTableEntries.putByte(Frame.SAME_FRAME_EXTENDED + numLocal).putShort(offsetDelta); + for (int i = 0; i < numLocal; ++i) { putFrameType(local[i]); } break; case Opcodes.F_CHOP: - currentLocals -= nLocal; - stackMapTableEntries.putByte(Frame.SAME_FRAME_EXTENDED - nLocal).putShort(offsetDelta); + currentLocals -= numLocal; + stackMapTableEntries.putByte(Frame.SAME_FRAME_EXTENDED - numLocal).putShort(offsetDelta); break; case Opcodes.F_SAME: if (offsetDelta < 64) { @@ -855,8 +854,8 @@ final class MethodWriter extends MethodVisitor { } if (compute == COMPUTE_MAX_STACK_AND_LOCAL_FROM_FRAMES) { - relativeStackSize = nStack; - for (int i = 0; i < nStack; ++i) { + relativeStackSize = numStack; + for (int i = 0; i < numStack; ++i) { if (stack[i] == Opcodes.LONG || stack[i] == Opcodes.DOUBLE) { relativeStackSize++; } @@ -866,7 +865,7 @@ final class MethodWriter extends MethodVisitor { } } - maxStack = Math.max(maxStack, nStack); + maxStack = Math.max(maxStack, numStack); maxLocals = Math.max(maxLocals, currentLocals); } @@ -1649,7 +1648,7 @@ final class MethodWriter extends MethodVisitor { code.data[endOffset] = (byte) Opcodes.ATHROW; // Emit a frame for this unreachable block, with no local and a Throwable on the stack // (so that the ATHROW could consume this Throwable if it were reachable). - int frameIndex = visitFrameStart(startOffset, /* nLocal = */ 0, /* nStack = */ 1); + int frameIndex = visitFrameStart(startOffset, /* numLocal = */ 0, /* numStack = */ 1); currentFrame[frameIndex] = Frame.getAbstractTypeFromInternalName(symbolTable, "java/lang/Throwable"); visitFrameEnd(); @@ -1821,18 +1820,18 @@ final class MethodWriter extends MethodVisitor { * Starts the visit of a new stack map frame, stored in {@link #currentFrame}. * * @param offset the bytecode offset of the instruction to which the frame corresponds. - * @param nLocal the number of local variables in the frame. - * @param nStack the number of stack elements in the frame. + * @param numLocal the number of local variables in the frame. + * @param numStack the number of stack elements in the frame. * @return the index of the next element to be written in this frame. */ - int visitFrameStart(final int offset, final int nLocal, final int nStack) { - int frameLength = 3 + nLocal + nStack; + int visitFrameStart(final int offset, final int numLocal, final int numStack) { + int frameLength = 3 + numLocal + numStack; if (currentFrame == null || currentFrame.length < frameLength) { currentFrame = new int[frameLength]; } currentFrame[0] = offset; - currentFrame[1] = nLocal; - currentFrame[2] = nStack; + currentFrame[1] = numLocal; + currentFrame[2] = numStack; return 3; } @@ -1865,25 +1864,25 @@ final class MethodWriter extends MethodVisitor { /** Compresses and writes {@link #currentFrame} in a new StackMapTable entry. */ private void putFrame() { - final int nLocal = currentFrame[1]; - final int nStack = currentFrame[2]; + final int numLocal = currentFrame[1]; + final int numStack = currentFrame[2]; if (symbolTable.getMajorVersion() < Opcodes.V1_6) { // Generate a StackMap attribute entry, which are always uncompressed. - stackMapTableEntries.putShort(currentFrame[0]).putShort(nLocal); - putAbstractTypes(3, 3 + nLocal); - stackMapTableEntries.putShort(nStack); - putAbstractTypes(3 + nLocal, 3 + nLocal + nStack); + stackMapTableEntries.putShort(currentFrame[0]).putShort(numLocal); + putAbstractTypes(3, 3 + numLocal); + stackMapTableEntries.putShort(numStack); + putAbstractTypes(3 + numLocal, 3 + numLocal + numStack); return; } final int offsetDelta = stackMapTableNumberOfEntries == 0 ? currentFrame[0] : currentFrame[0] - previousFrame[0] - 1; - final int previousNlocal = previousFrame[1]; - final int nLocalDelta = nLocal - previousNlocal; + final int previousNumlocal = previousFrame[1]; + final int numLocalDelta = numLocal - previousNumlocal; int type = Frame.FULL_FRAME; - if (nStack == 0) { - switch (nLocalDelta) { + if (numStack == 0) { + switch (numLocalDelta) { case -3: case -2: case -1: @@ -1901,7 +1900,7 @@ final class MethodWriter extends MethodVisitor { // Keep the FULL_FRAME type. break; } - } else if (nLocalDelta == 0 && nStack == 1) { + } else if (numLocalDelta == 0 && numStack == 1) { type = offsetDelta < 63 ? Frame.SAME_LOCALS_1_STACK_ITEM_FRAME @@ -1910,7 +1909,7 @@ final class MethodWriter extends MethodVisitor { if (type != Frame.FULL_FRAME) { // Verify if locals are the same as in the previous frame. int frameIndex = 3; - for (int i = 0; i < previousNlocal && i < nLocal; i++) { + for (int i = 0; i < previousNumlocal && i < numLocal; i++) { if (currentFrame[frameIndex] != previousFrame[frameIndex]) { type = Frame.FULL_FRAME; break; @@ -1924,30 +1923,34 @@ final class MethodWriter extends MethodVisitor { break; case Frame.SAME_LOCALS_1_STACK_ITEM_FRAME: stackMapTableEntries.putByte(Frame.SAME_LOCALS_1_STACK_ITEM_FRAME + offsetDelta); - putAbstractTypes(3 + nLocal, 4 + nLocal); + putAbstractTypes(3 + numLocal, 4 + numLocal); break; case Frame.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED: stackMapTableEntries .putByte(Frame.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED) .putShort(offsetDelta); - putAbstractTypes(3 + nLocal, 4 + nLocal); + putAbstractTypes(3 + numLocal, 4 + numLocal); break; case Frame.SAME_FRAME_EXTENDED: stackMapTableEntries.putByte(Frame.SAME_FRAME_EXTENDED).putShort(offsetDelta); break; case Frame.CHOP_FRAME: - stackMapTableEntries.putByte(Frame.SAME_FRAME_EXTENDED + nLocalDelta).putShort(offsetDelta); + stackMapTableEntries + .putByte(Frame.SAME_FRAME_EXTENDED + numLocalDelta) + .putShort(offsetDelta); break; case Frame.APPEND_FRAME: - stackMapTableEntries.putByte(Frame.SAME_FRAME_EXTENDED + nLocalDelta).putShort(offsetDelta); - putAbstractTypes(3 + previousNlocal, 3 + nLocal); + stackMapTableEntries + .putByte(Frame.SAME_FRAME_EXTENDED + numLocalDelta) + .putShort(offsetDelta); + putAbstractTypes(3 + previousNumlocal, 3 + numLocal); break; case Frame.FULL_FRAME: default: - stackMapTableEntries.putByte(Frame.FULL_FRAME).putShort(offsetDelta).putShort(nLocal); - putAbstractTypes(3, 3 + nLocal); - stackMapTableEntries.putShort(nStack); - putAbstractTypes(3 + nLocal, 3 + nLocal + nStack); + stackMapTableEntries.putByte(Frame.FULL_FRAME).putShort(offsetDelta).putShort(numLocal); + putAbstractTypes(3, 3 + numLocal); + stackMapTableEntries.putShort(numStack); + putAbstractTypes(3 + numLocal, 3 + numLocal + numStack); } } diff --git a/spring-core/src/main/java/org/springframework/asm/Opcodes.java b/spring-core/src/main/java/org/springframework/asm/Opcodes.java index 40b1c7734b0..ee4b79e546f 100644 --- a/spring-core/src/main/java/org/springframework/asm/Opcodes.java +++ b/spring-core/src/main/java/org/springframework/asm/Opcodes.java @@ -38,6 +38,7 @@ package org.springframework.asm; * @author Eric Bruneton * @author Eugene Kuleshov */ +// DontCheck(InterfaceIsType): can't be fixed (for backward binary compatibility). public interface Opcodes { // ASM API versions. diff --git a/spring-core/src/main/java/org/springframework/asm/Symbol.java b/spring-core/src/main/java/org/springframework/asm/Symbol.java index c7e5877a387..1088bbff0b5 100644 --- a/spring-core/src/main/java/org/springframework/asm/Symbol.java +++ b/spring-core/src/main/java/org/springframework/asm/Symbol.java @@ -227,6 +227,8 @@ abstract class Symbol { } /** + * Returns the result {@link Type#getArgumentsAndReturnSizes} on {@link #value}. + * * @return the result {@link Type#getArgumentsAndReturnSizes} on {@link #value} (memoized in * {@link #info} for efficiency). This should only be used for {@link * #CONSTANT_METHODREF_TAG}, {@link #CONSTANT_INTERFACE_METHODREF_TAG} and {@link diff --git a/spring-core/src/main/java/org/springframework/asm/SymbolTable.java b/spring-core/src/main/java/org/springframework/asm/SymbolTable.java index 8b6dd351c56..4294fb6a357 100644 --- a/spring-core/src/main/java/org/springframework/asm/SymbolTable.java +++ b/spring-core/src/main/java/org/springframework/asm/SymbolTable.java @@ -39,58 +39,6 @@ package org.springframework.asm; */ final class SymbolTable { - /** - * An entry of a SymbolTable. This concrete and private subclass of {@link Symbol} adds two fields - * which are only used inside SymbolTable, to implement hash sets of symbols (in order to avoid - * duplicate symbols). See {@link #entries}. - * - * @author Eric Bruneton - */ - private static class Entry extends Symbol { - - /** The hash code of this entry. */ - final int hashCode; - - /** - * Another entry (and so on recursively) having the same hash code (modulo the size of {@link - * #entries}) as this one. - */ - Entry next; - - Entry( - final int index, - final int tag, - final String owner, - final String name, - final String value, - final long data, - final int hashCode) { - super(index, tag, owner, name, value, data); - this.hashCode = hashCode; - } - - Entry(final int index, final int tag, final String value, final int hashCode) { - super(index, tag, /* owner = */ null, /* name = */ null, value, /* data = */ 0); - this.hashCode = hashCode; - } - - Entry(final int index, final int tag, final String value, final long data, final int hashCode) { - super(index, tag, /* owner = */ null, /* name = */ null, value, data); - this.hashCode = hashCode; - } - - Entry( - final int index, final int tag, final String name, final String value, final int hashCode) { - super(index, tag, /* owner = */ null, name, value, /* data = */ 0); - this.hashCode = hashCode; - } - - Entry(final int index, final int tag, final long data, final int hashCode) { - super(index, tag, /* owner = */ null, /* name = */ null, /* value = */ null, data); - this.hashCode = hashCode; - } - } - /** * The ClassWriter to which this SymbolTable belongs. This is only used to get access to {@link * ClassWriter#getCommonSuperClass} and to serialize custom attributes with {@link @@ -224,7 +172,7 @@ final class SymbolTable { break; case Symbol.CONSTANT_INTEGER_TAG: case Symbol.CONSTANT_FLOAT_TAG: - addConstantInteger(itemIndex, itemTag, classReader.readInt(itemOffset)); + addConstantIntegerOrFloat(itemIndex, itemTag, classReader.readInt(itemOffset)); break; case Symbol.CONSTANT_NAME_AND_TYPE_TAG: addConstantNameAndType( @@ -234,10 +182,10 @@ final class SymbolTable { break; case Symbol.CONSTANT_LONG_TAG: case Symbol.CONSTANT_DOUBLE_TAG: - addConstantLong(itemIndex, itemTag, classReader.readLong(itemOffset)); + addConstantLongOrDouble(itemIndex, itemTag, classReader.readLong(itemOffset)); break; case Symbol.CONSTANT_UTF8_TAG: - addConstantUtf8(itemIndex, classReader.readUTF(itemIndex, charBuffer)); + addConstantUtf8(itemIndex, classReader.readUtf(itemIndex, charBuffer)); break; case Symbol.CONSTANT_METHOD_HANDLE_TAG: int memberRefItemOffset = @@ -331,6 +279,8 @@ final class SymbolTable { } /** + * Returns the ClassReader from which this SymbolTable was constructed. + * * @return the ClassReader from which this SymbolTable was constructed, or {@literal null} if it * was constructed from scratch. */ @@ -338,12 +288,20 @@ final class SymbolTable { return sourceClassReader; } - /** @return the major version of the class to which this symbol table belongs. */ + /** + * Returns the major version of the class to which this symbol table belongs. + * + * @return the major version of the class to which this symbol table belongs. + */ int getMajorVersion() { return majorVersion; } - /** @return the internal name of the class to which this symbol table belongs. */ + /** + * Returns the internal name of the class to which this symbol table belongs. + * + * @return the internal name of the class to which this symbol table belongs. + */ String getClassName() { return className; } @@ -362,12 +320,20 @@ final class SymbolTable { return addConstantClass(className).index; } - /** @return the number of items in this symbol table's constant_pool array (plus 1). */ + /** + * Returns the number of items in this symbol table's constant_pool array (plus 1). + * + * @return the number of items in this symbol table's constant_pool array (plus 1). + */ int getConstantPoolCount() { return constantPoolCount; } - /** @return the length in bytes of this symbol table's constant_pool array. */ + /** + * Returns the length in bytes of this symbol table's constant_pool array. + * + * @return the length in bytes of this symbol table's constant_pool array. + */ int getConstantPoolLength() { return constantPool.length; } @@ -418,6 +384,8 @@ final class SymbolTable { // ----------------------------------------------------------------------------------------------- /** + * Returns the list of entries which can potentially have the given hash code. + * * @param hashCode a {@link Entry#hashCode} value. * @return the list of entries which can potentially have the given hash code. The list is stored * via the {@link Entry#next} field. @@ -644,7 +612,7 @@ final class SymbolTable { * @return a new or already existing Symbol with the given value. */ Symbol addConstantInteger(final int value) { - return addConstantInteger(Symbol.CONSTANT_INTEGER_TAG, value); + return addConstantIntegerOrFloat(Symbol.CONSTANT_INTEGER_TAG, value); } /** @@ -655,7 +623,7 @@ final class SymbolTable { * @return a new or already existing Symbol with the given value. */ Symbol addConstantFloat(final float value) { - return addConstantInteger(Symbol.CONSTANT_FLOAT_TAG, Float.floatToRawIntBits(value)); + return addConstantIntegerOrFloat(Symbol.CONSTANT_FLOAT_TAG, Float.floatToRawIntBits(value)); } /** @@ -666,7 +634,7 @@ final class SymbolTable { * @param value an int or float. * @return a constant pool constant with the given tag and primitive values. */ - private Symbol addConstantInteger(final int tag, final int value) { + private Symbol addConstantIntegerOrFloat(final int tag, final int value) { int hashCode = hash(tag, value); Entry entry = get(hashCode); while (entry != null) { @@ -687,7 +655,7 @@ final class SymbolTable { * @param tag one of {@link Symbol#CONSTANT_INTEGER_TAG} or {@link Symbol#CONSTANT_FLOAT_TAG}. * @param value an int or float. */ - private void addConstantInteger(final int index, final int tag, final int value) { + private void addConstantIntegerOrFloat(final int index, final int tag, final int value) { add(new Entry(index, tag, value, hash(tag, value))); } @@ -699,7 +667,7 @@ final class SymbolTable { * @return a new or already existing Symbol with the given value. */ Symbol addConstantLong(final long value) { - return addConstantLong(Symbol.CONSTANT_LONG_TAG, value); + return addConstantLongOrDouble(Symbol.CONSTANT_LONG_TAG, value); } /** @@ -710,7 +678,7 @@ final class SymbolTable { * @return a new or already existing Symbol with the given value. */ Symbol addConstantDouble(final double value) { - return addConstantLong(Symbol.CONSTANT_DOUBLE_TAG, Double.doubleToRawLongBits(value)); + return addConstantLongOrDouble(Symbol.CONSTANT_DOUBLE_TAG, Double.doubleToRawLongBits(value)); } /** @@ -721,7 +689,7 @@ final class SymbolTable { * @param value a long or double. * @return a constant pool constant with the given tag and primitive values. */ - private Symbol addConstantLong(final int tag, final long value) { + private Symbol addConstantLongOrDouble(final int tag, final long value) { int hashCode = hash(tag, value); Entry entry = get(hashCode); while (entry != null) { @@ -737,13 +705,14 @@ final class SymbolTable { } /** - * Adds a new CONSTANT_Double_info to the constant pool of this symbol table. + * Adds a new CONSTANT_Long_info or CONSTANT_Double_info to the constant pool of this symbol + * table. * * @param index the constant pool index of the new Symbol. * @param tag one of {@link Symbol#CONSTANT_LONG_TAG} or {@link Symbol#CONSTANT_DOUBLE_TAG}. * @param value a long or double. */ - private void addConstantLong(final int index, final int tag, final long value) { + private void addConstantLongOrDouble(final int index, final int tag, final long value) { add(new Entry(index, tag, value, hash(tag, value))); } @@ -1149,6 +1118,8 @@ final class SymbolTable { // ----------------------------------------------------------------------------------------------- /** + * Returns the type table element whose index is given. + * * @param typeIndex a type table index. * @return the type table element whose index is given. */ @@ -1172,7 +1143,7 @@ final class SymbolTable { } entry = entry.next; } - return addType(new Entry(typeCount, Symbol.TYPE_TAG, value, hashCode)); + return addTypeInternal(new Entry(typeCount, Symbol.TYPE_TAG, value, hashCode)); } /** @@ -1196,7 +1167,7 @@ final class SymbolTable { } entry = entry.next; } - return addType( + return addTypeInternal( new Entry(typeCount, Symbol.UNINITIALIZED_TYPE_TAG, value, bytecodeOffset, hashCode)); } @@ -1237,7 +1208,7 @@ final class SymbolTable { * @return the index in {@link #typeTable} where the given type was added, which is also equal to * entry's index by hypothesis. */ - private int addType(final Entry entry) { + private int addTypeInternal(final Entry entry) { if (typeTable == null) { typeTable = new Entry[16]; } @@ -1292,4 +1263,56 @@ final class SymbolTable { final int value4) { return 0x7FFFFFFF & (tag + value1.hashCode() * value2.hashCode() * value3.hashCode() * value4); } + + /** + * An entry of a SymbolTable. This concrete and private subclass of {@link Symbol} adds two fields + * which are only used inside SymbolTable, to implement hash sets of symbols (in order to avoid + * duplicate symbols). See {@link #entries}. + * + * @author Eric Bruneton + */ + private static class Entry extends Symbol { + + /** The hash code of this entry. */ + final int hashCode; + + /** + * Another entry (and so on recursively) having the same hash code (modulo the size of {@link + * #entries}) as this one. + */ + Entry next; + + Entry( + final int index, + final int tag, + final String owner, + final String name, + final String value, + final long data, + final int hashCode) { + super(index, tag, owner, name, value, data); + this.hashCode = hashCode; + } + + Entry(final int index, final int tag, final String value, final int hashCode) { + super(index, tag, /* owner = */ null, /* name = */ null, value, /* data = */ 0); + this.hashCode = hashCode; + } + + Entry(final int index, final int tag, final String value, final long data, final int hashCode) { + super(index, tag, /* owner = */ null, /* name = */ null, value, data); + this.hashCode = hashCode; + } + + Entry( + final int index, final int tag, final String name, final String value, final int hashCode) { + super(index, tag, /* owner = */ null, name, value, /* data = */ 0); + this.hashCode = hashCode; + } + + Entry(final int index, final int tag, final long data, final int hashCode) { + super(index, tag, /* owner = */ null, /* name = */ null, /* value = */ null, data); + this.hashCode = hashCode; + } + } } diff --git a/spring-core/src/main/java/org/springframework/asm/Type.java b/spring-core/src/main/java/org/springframework/asm/Type.java index e71c18a56a0..52676cefb5a 100644 --- a/spring-core/src/main/java/org/springframework/asm/Type.java +++ b/spring-core/src/main/java/org/springframework/asm/Type.java @@ -146,10 +146,6 @@ public class Type { */ private final int valueEnd; - // ----------------------------------------------------------------------------------------------- - // Constructors - // ----------------------------------------------------------------------------------------------- - /** * Constructs a reference type. * @@ -167,6 +163,10 @@ public class Type { this.valueEnd = valueEnd; } + // ----------------------------------------------------------------------------------------------- + // Methods to get Type(s) from a descriptor, a reflected Method or Constructor, other types, etc. + // ----------------------------------------------------------------------------------------------- + /** * Returns the {@link Type} corresponding to the given type descriptor. * @@ -174,40 +174,7 @@ public class Type { * @return the {@link Type} corresponding to the given type descriptor. */ public static Type getType(final String typeDescriptor) { - return getType(typeDescriptor, 0, typeDescriptor.length()); - } - - /** - * Returns the {@link Type} corresponding to the given internal name. - * - * @param internalName an internal name. - * @return the {@link Type} corresponding to the given internal name. - */ - public static Type getObjectType(final String internalName) { - return new Type( - internalName.charAt(0) == '[' ? ARRAY : INTERNAL, internalName, 0, internalName.length()); - } - - /** - * Returns the {@link Type} corresponding to the given method descriptor. Equivalent to - * Type.getType(methodDescriptor). - * - * @param methodDescriptor a method descriptor. - * @return the {@link Type} corresponding to the given method descriptor. - */ - public static Type getMethodType(final String methodDescriptor) { - return new Type(METHOD, methodDescriptor, 0, methodDescriptor.length()); - } - - /** - * Returns the method {@link Type} corresponding to the given argument and return types. - * - * @param returnType the return type of the method. - * @param argumentTypes the argument types of the method. - * @return the method {@link Type} corresponding to the given argument and return types. - */ - public static Type getMethodType(final Type returnType, final Type... argumentTypes) { - return getType(getMethodDescriptor(returnType, argumentTypes)); + return getTypeInternal(typeDescriptor, 0, typeDescriptor.length()); } /** @@ -264,6 +231,60 @@ public class Type { return getType(getMethodDescriptor(method)); } + /** + * Returns the type of the elements of this array type. This method should only be used for an + * array type. + * + * @return Returns the type of the elements of this array type. + */ + public Type getElementType() { + final int numDimensions = getDimensions(); + return getTypeInternal(valueBuffer, valueBegin + numDimensions, valueEnd); + } + + /** + * Returns the {@link Type} corresponding to the given internal name. + * + * @param internalName an internal name. + * @return the {@link Type} corresponding to the given internal name. + */ + public static Type getObjectType(final String internalName) { + return new Type( + internalName.charAt(0) == '[' ? ARRAY : INTERNAL, internalName, 0, internalName.length()); + } + + /** + * Returns the {@link Type} corresponding to the given method descriptor. Equivalent to + * Type.getType(methodDescriptor). + * + * @param methodDescriptor a method descriptor. + * @return the {@link Type} corresponding to the given method descriptor. + */ + public static Type getMethodType(final String methodDescriptor) { + return new Type(METHOD, methodDescriptor, 0, methodDescriptor.length()); + } + + /** + * Returns the method {@link Type} corresponding to the given argument and return types. + * + * @param returnType the return type of the method. + * @param argumentTypes the argument types of the method. + * @return the method {@link Type} corresponding to the given argument and return types. + */ + public static Type getMethodType(final Type returnType, final Type... argumentTypes) { + return getType(getMethodDescriptor(returnType, argumentTypes)); + } + + /** + * Returns the argument types of methods of this type. This method should only be used for method + * types. + * + * @return the argument types of methods of this type. + */ + public Type[] getArgumentTypes() { + return getArgumentTypes(getDescriptor()); + } + /** * Returns the {@link Type} values corresponding to the argument types of the given method * descriptor. @@ -307,7 +328,7 @@ public class Type { } } argumentTypes[currentArgumentTypeIndex++] = - getType(methodDescriptor, currentArgumentTypeOffset, currentOffset); + getTypeInternal(methodDescriptor, currentArgumentTypeOffset, currentOffset); } return argumentTypes; } @@ -327,6 +348,16 @@ public class Type { return types; } + /** + * Returns the return type of methods of this type. This method should only be used for method + * types. + * + * @return the return type of methods of this type. + */ + public Type getReturnType() { + return getReturnType(getDescriptor()); + } + /** * Returns the {@link Type} corresponding to the return type of the given method descriptor. * @@ -347,7 +378,7 @@ public class Type { } } } - return getType(methodDescriptor, currentOffset + 1, methodDescriptor.length()); + return getTypeInternal(methodDescriptor, currentOffset + 1, methodDescriptor.length()); } /** @@ -360,47 +391,6 @@ public class Type { return getType(method.getReturnType()); } - /** - * Computes the size of the arguments and of the return value of a method. - * - * @param methodDescriptor a method descriptor. - * @return the size of the arguments of the method (plus one for the implicit this argument), - * argumentsSize, and the size of its return value, returnSize, packed into a single int i = - * {@code (argumentsSize << 2) | returnSize} (argumentsSize is therefore equal to {@code - * i >> 2}, and returnSize to {@code i & 0x03}). - */ - public static int getArgumentsAndReturnSizes(final String methodDescriptor) { - int argumentsSize = 1; - // Skip the first character, which is always a '('. - int currentOffset = 1; - int currentChar = methodDescriptor.charAt(currentOffset); - // Parse the argument types and compute their size, one at a each loop iteration. - while (currentChar != ')') { - if (currentChar == 'J' || currentChar == 'D') { - currentOffset++; - argumentsSize += 2; - } else { - while (methodDescriptor.charAt(currentOffset) == '[') { - currentOffset++; - } - if (methodDescriptor.charAt(currentOffset++) == 'L') { - while (methodDescriptor.charAt(currentOffset++) != ';') { - // Skip the argument descriptor content. - } - } - argumentsSize += 1; - } - currentChar = methodDescriptor.charAt(currentOffset); - } - currentChar = methodDescriptor.charAt(currentOffset + 1); - if (currentChar == 'V') { - return argumentsSize << 2; - } else { - int returnSize = (currentChar == 'J' || currentChar == 'D') ? 2 : 1; - return argumentsSize << 2 | returnSize; - } - } - /** * Returns the {@link Type} corresponding to the given field or method descriptor. * @@ -411,7 +401,7 @@ public class Type { * descriptorBuffer. * @return the {@link Type} corresponding to the given type descriptor. */ - private static Type getType( + private static Type getTypeInternal( final String descriptorBuffer, final int descriptorBegin, final int descriptorEnd) { switch (descriptorBuffer.charAt(descriptorBegin)) { case 'V': @@ -444,45 +434,9 @@ public class Type { } // ----------------------------------------------------------------------------------------------- - // Accessors + // Methods to get class names, internal names or descriptors. // ----------------------------------------------------------------------------------------------- - /** - * Returns the sort of this type. - * - * @return {@link #VOID}, {@link #BOOLEAN}, {@link #CHAR}, {@link #BYTE}, {@link #SHORT}, {@link - * #INT}, {@link #FLOAT}, {@link #LONG}, {@link #DOUBLE}, {@link #ARRAY}, {@link #OBJECT} or - * {@link #METHOD}. - */ - public int getSort() { - return sort == INTERNAL ? OBJECT : sort; - } - - /** - * Returns the number of dimensions of this array type. This method should only be used for an - * array type. - * - * @return the number of dimensions of this array type. - */ - public int getDimensions() { - int numDimensions = 1; - while (valueBuffer.charAt(valueBegin + numDimensions) == '[') { - numDimensions++; - } - return numDimensions; - } - - /** - * Returns the type of the elements of this array type. This method should only be used for an - * array type. - * - * @return Returns the type of the elements of this array type. - */ - public Type getElementType() { - final int numDimensions = getDimensions(); - return getType(valueBuffer, valueBegin + numDimensions, valueEnd); - } - /** * Returns the binary name of the class corresponding to this type. This method must not be used * on method types. @@ -535,42 +489,16 @@ public class Type { } /** - * Returns the argument types of methods of this type. This method should only be used for method - * types. - * - * @return the argument types of methods of this type. - */ - public Type[] getArgumentTypes() { - return getArgumentTypes(getDescriptor()); - } - - /** - * Returns the return type of methods of this type. This method should only be used for method - * types. - * - * @return the return type of methods of this type. - */ - public Type getReturnType() { - return getReturnType(getDescriptor()); - } - - /** - * Returns the size of the arguments and of the return value of methods of this type. This method - * should only be used for method types. + * Returns the internal name of the given class. The internal name of a class is its fully + * qualified name, as returned by Class.getName(), where '.' are replaced by '/'. * - * @return the size of the arguments of the method (plus one for the implicit this argument), - * argumentsSize, and the size of its return value, returnSize, packed into a single int i = - * {@code (argumentsSize << 2) | returnSize} (argumentsSize is therefore equal to {@code - * i >> 2}, and returnSize to {@code i & 0x03}). + * @param clazz an object or array class. + * @return the internal name of the given class. */ - public int getArgumentsAndReturnSizes() { - return getArgumentsAndReturnSizes(getDescriptor()); + public static String getInternalName(final Class clazz) { + return clazz.getName().replace('.', '/'); } - // ----------------------------------------------------------------------------------------------- - // Conversion to type descriptors - // ----------------------------------------------------------------------------------------------- - /** * Returns the descriptor corresponding to this type. * @@ -590,57 +518,6 @@ public class Type { } } - /** - * Returns the descriptor corresponding to the given argument and return types. - * - * @param returnType the return type of the method. - * @param argumentTypes the argument types of the method. - * @return the descriptor corresponding to the given argument and return types. - */ - public static String getMethodDescriptor(final Type returnType, final Type... argumentTypes) { - StringBuilder stringBuilder = new StringBuilder(); - stringBuilder.append('('); - for (int i = 0; i < argumentTypes.length; ++i) { - argumentTypes[i].appendDescriptor(stringBuilder); - } - stringBuilder.append(')'); - returnType.appendDescriptor(stringBuilder); - return stringBuilder.toString(); - } - - /** - * Appends the descriptor corresponding to this type to the given string buffer. - * - * @param stringBuilder the string builder to which the descriptor must be appended. - */ - private void appendDescriptor(final StringBuilder stringBuilder) { - if (sort == OBJECT) { - stringBuilder.append(valueBuffer, valueBegin - 1, valueEnd + 1); - } else if (sort == INTERNAL) { - stringBuilder.append('L'); - stringBuilder.append(valueBuffer, valueBegin, valueEnd); - stringBuilder.append(';'); - } else { - stringBuilder.append(valueBuffer, valueBegin, valueEnd); - } - } - - // ----------------------------------------------------------------------------------------------- - // Direct conversion from classes to type descriptors, - // without intermediate Type objects - // ----------------------------------------------------------------------------------------------- - - /** - * Returns the internal name of the given class. The internal name of a class is its fully - * qualified name, as returned by Class.getName(), where '.' are replaced by '/'. - * - * @param clazz an object or array class. - * @return the internal name of the given class. - */ - public static String getInternalName(final Class clazz) { - return clazz.getName().replace('.', '/'); - } - /** * Returns the descriptor corresponding to the given class. * @@ -649,7 +526,7 @@ public class Type { */ public static String getDescriptor(final Class clazz) { StringBuilder stringBuilder = new StringBuilder(); - appendDescriptor(stringBuilder, clazz); + appendDescriptor(clazz, stringBuilder); return stringBuilder.toString(); } @@ -664,11 +541,29 @@ public class Type { stringBuilder.append('('); Class[] parameters = constructor.getParameterTypes(); for (int i = 0; i < parameters.length; ++i) { - appendDescriptor(stringBuilder, parameters[i]); + appendDescriptor(parameters[i], stringBuilder); } return stringBuilder.append(")V").toString(); } + /** + * Returns the descriptor corresponding to the given argument and return types. + * + * @param returnType the return type of the method. + * @param argumentTypes the argument types of the method. + * @return the descriptor corresponding to the given argument and return types. + */ + public static String getMethodDescriptor(final Type returnType, final Type... argumentTypes) { + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append('('); + for (int i = 0; i < argumentTypes.length; ++i) { + argumentTypes[i].appendDescriptor(stringBuilder); + } + stringBuilder.append(')'); + returnType.appendDescriptor(stringBuilder); + return stringBuilder.toString(); + } + /** * Returns the descriptor corresponding to the given method. * @@ -680,20 +575,37 @@ public class Type { stringBuilder.append('('); Class[] parameters = method.getParameterTypes(); for (int i = 0; i < parameters.length; ++i) { - appendDescriptor(stringBuilder, parameters[i]); + appendDescriptor(parameters[i], stringBuilder); } stringBuilder.append(')'); - appendDescriptor(stringBuilder, method.getReturnType()); + appendDescriptor(method.getReturnType(), stringBuilder); return stringBuilder.toString(); } /** - * Appends the descriptor of the given class to the given string builder. + * Appends the descriptor corresponding to this type to the given string buffer. * * @param stringBuilder the string builder to which the descriptor must be appended. + */ + private void appendDescriptor(final StringBuilder stringBuilder) { + if (sort == OBJECT) { + stringBuilder.append(valueBuffer, valueBegin - 1, valueEnd + 1); + } else if (sort == INTERNAL) { + stringBuilder.append('L'); + stringBuilder.append(valueBuffer, valueBegin, valueEnd); + stringBuilder.append(';'); + } else { + stringBuilder.append(valueBuffer, valueBegin, valueEnd); + } + } + + /** + * Appends the descriptor of the given class to the given string builder. + * * @param clazz the class whose descriptor must be computed. + * @param stringBuilder the string builder to which the descriptor must be appended. */ - private static void appendDescriptor(final StringBuilder stringBuilder, final Class clazz) { + private static void appendDescriptor(final Class clazz, final StringBuilder stringBuilder) { Class currentClass = clazz; while (currentClass.isArray()) { stringBuilder.append('['); @@ -736,9 +648,34 @@ public class Type { } // ----------------------------------------------------------------------------------------------- - // Corresponding size and opcodes + // Methods to get the sort, dimension, size, and opcodes corresponding to a Type or descriptor. // ----------------------------------------------------------------------------------------------- + /** + * Returns the sort of this type. + * + * @return {@link #VOID}, {@link #BOOLEAN}, {@link #CHAR}, {@link #BYTE}, {@link #SHORT}, {@link + * #INT}, {@link #FLOAT}, {@link #LONG}, {@link #DOUBLE}, {@link #ARRAY}, {@link #OBJECT} or + * {@link #METHOD}. + */ + public int getSort() { + return sort == INTERNAL ? OBJECT : sort; + } + + /** + * Returns the number of dimensions of this array type. This method should only be used for an + * array type. + * + * @return the number of dimensions of this array type. + */ + public int getDimensions() { + int numDimensions = 1; + while (valueBuffer.charAt(valueBegin + numDimensions) == '[') { + numDimensions++; + } + return numDimensions; + } + /** * Returns the size of values of this type. This method must not be used for method types. * @@ -767,6 +704,60 @@ public class Type { } } + /** + * Returns the size of the arguments and of the return value of methods of this type. This method + * should only be used for method types. + * + * @return the size of the arguments of the method (plus one for the implicit this argument), + * argumentsSize, and the size of its return value, returnSize, packed into a single int i = + * {@code (argumentsSize << 2) | returnSize} (argumentsSize is therefore equal to {@code + * i >> 2}, and returnSize to {@code i & 0x03}). + */ + public int getArgumentsAndReturnSizes() { + return getArgumentsAndReturnSizes(getDescriptor()); + } + + /** + * Computes the size of the arguments and of the return value of a method. + * + * @param methodDescriptor a method descriptor. + * @return the size of the arguments of the method (plus one for the implicit this argument), + * argumentsSize, and the size of its return value, returnSize, packed into a single int i = + * {@code (argumentsSize << 2) | returnSize} (argumentsSize is therefore equal to {@code + * i >> 2}, and returnSize to {@code i & 0x03}). + */ + public static int getArgumentsAndReturnSizes(final String methodDescriptor) { + int argumentsSize = 1; + // Skip the first character, which is always a '('. + int currentOffset = 1; + int currentChar = methodDescriptor.charAt(currentOffset); + // Parse the argument types and compute their size, one at a each loop iteration. + while (currentChar != ')') { + if (currentChar == 'J' || currentChar == 'D') { + currentOffset++; + argumentsSize += 2; + } else { + while (methodDescriptor.charAt(currentOffset) == '[') { + currentOffset++; + } + if (methodDescriptor.charAt(currentOffset++) == 'L') { + while (methodDescriptor.charAt(currentOffset++) != ';') { + // Skip the argument descriptor content. + } + } + argumentsSize += 1; + } + currentChar = methodDescriptor.charAt(currentOffset); + } + currentChar = methodDescriptor.charAt(currentOffset + 1); + if (currentChar == 'V') { + return argumentsSize << 2; + } else { + int returnSize = (currentChar == 'J' || currentChar == 'D') ? 2 : 1; + return argumentsSize << 2 | returnSize; + } + } + /** * Returns a JVM instruction opcode adapted to this {@link Type}. This method must not be used for * method types. @@ -841,7 +832,7 @@ public class Type { } // ----------------------------------------------------------------------------------------------- - // Equals, hashCode and toString + // Equals, hashCode and toString. // ----------------------------------------------------------------------------------------------- /**