firstAttribute = null; compute = hasFrames ? MethodWriter.COMPUTE_INSERTED_FRAMES : MethodWriter.COMPUTE_NOTHING; new ClassReader(classFile, 0, /* checkClassVersion = */ false) .accept( this, attributes,
final int maxStack = readUnsignedShort(currentOffset); final int maxLocals = readUnsignedShort(currentOffset + 2); final int codeLength = readInt(currentOffset + 4); currentOffset += 8; case Constants.IFNULL: case Constants.IFNONNULL: createLabel(bytecodeOffset + readShort(currentOffset + 1), labels); currentOffset += 3; break; case Constants.ASM_IFNULL: case Constants.ASM_IFNONNULL: createLabel(bytecodeOffset + readUnsignedShort(currentOffset + 1), labels); currentOffset += 3; break; case Constants.JSR_W: case Constants.ASM_GOTO_W: createLabel(bytecodeOffset + readInt(currentOffset + 1), labels); currentOffset += 5; break; createLabel(bytecodeOffset + readInt(currentOffset), labels); int numTableEntries = readInt(currentOffset + 8) - readInt(currentOffset + 4) + 1; currentOffset += 12; createLabel(bytecodeOffset + readInt(currentOffset), labels); currentOffset += 4;
/** * Reads the target and creates destination class. */ protected void process() { if (targetInputStream == null) { throw new ProxettaException("Target missing: " + targetClassName); } // create class reader final ClassReader classReader; try { classReader = new ClassReader(targetInputStream); } catch (IOException ioex) { throw new ProxettaException("Error reading class input stream", ioex); } // reads information final TargetClassInfoReader targetClassInfoReader = new TargetClassInfoReader(proxetta.getClassLoader()); classReader.accept(targetClassInfoReader, 0); this.destClassWriter = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES); // create proxy if (log.isDebugEnabled()) { log.debug("processing: " + classReader.getClassName()); } WorkData wd = process(classReader, targetClassInfoReader); // store important data proxyApplied = wd.proxyApplied; proxyClassName = wd.thisReference.replace('/', '.'); }
int currentAttributeOffset = getFirstAttributeOffset(); int[] currentBootstrapMethodOffsets = null; for (int i = readUnsignedShort(currentAttributeOffset - 2); i > 0; --i) { String attributeName = readUTF8(currentAttributeOffset, charBuffer); int attributeLength = readInt(currentAttributeOffset + 2); currentAttributeOffset += 6; if (Constants.BOOTSTRAP_METHODS.equals(attributeName)) { currentBootstrapMethodOffsets = new int[readUnsignedShort(currentAttributeOffset)]; 4 + readUnsignedShort(currentBootstrapMethodOffset + 2) * 2;
break; case Frame.ITEM_OBJECT: frame[index] = readClass(currentOffset, charBuffer); currentOffset += 2; break; case Frame.ITEM_UNINITIALIZED: frame[index] = createLabel(readUnsignedShort(currentOffset), labels); currentOffset += 2; break;
offsetDelta = frameType - Frame.SAME_LOCALS_1_STACK_ITEM_FRAME; currentOffset = readVerificationTypeInfo( currentOffset, context.currentFrameStackTypes, 0, charBuffer, labels); context.currentFrameType = Opcodes.F_SAME1; context.currentFrameStackCount = 1; } else if (frameType >= Frame.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED) { offsetDelta = readUnsignedShort(currentOffset); currentOffset += 2; if (frameType == Frame.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED) { currentOffset = readVerificationTypeInfo( currentOffset, context.currentFrameStackTypes, 0, charBuffer, labels); context.currentFrameType = Opcodes.F_SAME1; for (int k = frameType - Frame.SAME_FRAME_EXTENDED; k > 0; k--) { currentOffset = readVerificationTypeInfo( currentOffset, context.currentFrameLocalTypes, local++, charBuffer, labels); context.currentFrameStackCount = 0; } else { final int numberOfLocals = readUnsignedShort(currentOffset); currentOffset += 2; context.currentFrameType = Opcodes.F_FULL; for (int local = 0; local < numberOfLocals; ++local) { currentOffset = readVerificationTypeInfo(
int accessFlags = readUnsignedShort(currentOffset); String thisClass = readClass(currentOffset + 2, charBuffer); String superClass = readClass(currentOffset + 4, charBuffer); String[] interfaces = new String[readUnsignedShort(currentOffset + 6)]; currentOffset += 8; for (int i = 0; i < interfaces.length; ++i) { interfaces[i] = readClass(currentOffset, charBuffer); currentOffset += 2; int currentAttributeOffset = getFirstAttributeOffset(); for (int i = readUnsignedShort(currentAttributeOffset - 2); i > 0; --i) { String attributeName = readUTF8(currentAttributeOffset, charBuffer); int attributeLength = readInt(currentAttributeOffset + 2); currentAttributeOffset += 6; sourceFile = readUTF8(currentAttributeOffset, charBuffer); } else if (Constants.INNER_CLASSES.equals(attributeName)) { innerClassesOffset = currentAttributeOffset; enclosingMethodOffset = currentAttributeOffset; } else if (Constants.NEST_HOST.equals(attributeName)) { nestHostClass = readClass(currentAttributeOffset, charBuffer); } else if (Constants.NEST_MEMBERS.equals(attributeName)) { nestMembersOffset = currentAttributeOffset; } else if (Constants.SIGNATURE.equals(attributeName)) { signature = readUTF8(currentAttributeOffset, charBuffer); } else if (Constants.RUNTIME_VISIBLE_ANNOTATIONS.equals(attributeName)) { runtimeVisibleAnnotationsOffset = currentAttributeOffset;
int constantPoolOffset = classReader.getItem(1) - 1; int constantPoolLength = classReader.header - constantPoolOffset; constantPoolCount = classReader.getItemCount(); constantPool = new ByteVector(constantPoolLength); constantPool.putByteArray(inputBytes, constantPoolOffset, constantPoolLength); char[] charBuffer = new char[classReader.getMaxStringLength()]; boolean hasBootstrapMethods = false; int itemIndex = 1; while (itemIndex < constantPoolCount) { int itemOffset = classReader.getItem(itemIndex); int itemTag = inputBytes[itemOffset - 1]; int nameAndTypeItemOffset; case Symbol.CONSTANT_INTERFACE_METHODREF_TAG: nameAndTypeItemOffset = classReader.getItem(classReader.readUnsignedShort(itemOffset + 2)); addConstantMemberReference( itemIndex, itemTag, classReader.readClass(itemOffset, charBuffer), classReader.readUTF8(nameAndTypeItemOffset, charBuffer), classReader.readUTF8(nameAndTypeItemOffset + 2, charBuffer)); break; case Symbol.CONSTANT_INTEGER_TAG: case Symbol.CONSTANT_FLOAT_TAG: addConstantIntegerOrFloat(itemIndex, itemTag, classReader.readInt(itemOffset)); break; case Symbol.CONSTANT_NAME_AND_TYPE_TAG:
int[] typeAnnotationsOffsets = new int[readUnsignedShort(currentOffset)]; currentOffset += 2; int targetType = readInt(currentOffset); switch (targetType >>> 24) { case TypeReference.LOCAL_VARIABLE: int tableLength = readUnsignedShort(currentOffset + 1); currentOffset += 3; while (tableLength-- > 0) { int startPc = readUnsignedShort(currentOffset); int length = readUnsignedShort(currentOffset + 2); createLabel(startPc, context.currentMethodLabels); createLabel(startPc + length, context.currentMethodLabels); int pathLength = readByte(currentOffset); if ((targetType >>> 24) == TypeReference.EXCEPTION_PARAMETER) { String annotationDescriptor = readUTF8(currentOffset, charBuffer); currentOffset += 2; readElementValues( methodVisitor.visitTryCatchAnnotation( targetType & 0xFFFFFF00, path, annotationDescriptor, visible), readElementValues( /* annotationVisitor = */ null, currentOffset, /* named = */ true, charBuffer);
cr = new ClassReader(inputStream); } catch (IOException ioex) { throw new ProxettaException("Unable to inspect super class: " + nextSupername, ioex); cr.accept(new SuperClassVisitor(), 0); if (cr.getInterfaces() != null) { Collections.addAll(allInterfaces, cr.getInterfaces()); try { inputStream = ClassLoaderUtil.getClassAsStream(next, classLoader); cr = new ClassReader(inputStream); cr.accept(new SuperClassVisitor(), 0); if (cr.getInterfaces() != null) { for (String newInterface : cr.getInterfaces()) { if (!allInterfaces.contains(newInterface) && !todoInterfaces.contains(newInterface)) {
int currentOffset = typeAnnotationOffset; int targetType = readInt(typeAnnotationOffset); switch (targetType >>> 24) { case TypeReference.CLASS_TYPE_PARAMETER: case TypeReference.RESOURCE_VARIABLE: targetType &= 0xFF000000; int tableLength = readUnsignedShort(currentOffset + 1); currentOffset += 3; context.currentLocalVariableAnnotationRangeStarts = new Label[tableLength]; context.currentLocalVariableAnnotationRangeIndices = new int[tableLength]; for (int i = 0; i < tableLength; ++i) { int startPc = readUnsignedShort(currentOffset); int length = readUnsignedShort(currentOffset + 2); int index = readUnsignedShort(currentOffset + 4); currentOffset += 6; context.currentLocalVariableAnnotationRangeStarts[i] = createLabel(startPc, context.currentMethodLabels); context.currentLocalVariableAnnotationRangeEnds[i] = createLabel(startPc + length, context.currentMethodLabels); context.currentLocalVariableAnnotationRangeIndices[i] = index; int pathLength = readByte(currentOffset); context.currentTypeAnnotationTargetPath = pathLength == 0 ? null : new TypePath(b, currentOffset);
/** * Makes the given visitor visit the JVMS ClassFile structure passed to the constructor of this * {@link ClassReader}. * * @param classVisitor the visitor that must visit this class. * @param parsingOptions the options to use to parse this class. One or more of {@link * #SKIP_CODE}, {@link #SKIP_DEBUG}, {@link #SKIP_FRAMES} or {@link #EXPAND_FRAMES}. */ public void accept(final ClassVisitor classVisitor, final int parsingOptions) { accept(classVisitor, new Attribute[0], parsingOptions); }
/** * Creates advice's class reader. */ private ClassReader createAdviceClassReader(final Class<? extends ProxyAdvice> advice) { InputStream inputStream = null; try { inputStream = ClassLoaderUtil.getClassAsStream(advice); return new ClassReader(inputStream); } catch (IOException ioex) { throw new ProxettaException(ioex); } finally { StreamUtil.close(inputStream); } }
int accessFlags = readUnsignedShort(currentOffset); String thisClass = readClass(currentOffset + 2, charBuffer); String superClass = readClass(currentOffset + 4, charBuffer); String[] interfaces = new String[readUnsignedShort(currentOffset + 6)]; currentOffset += 8; for (int i = 0; i < interfaces.length; ++i) { interfaces[i] = readClass(currentOffset, charBuffer); currentOffset += 2; int currentAttributeOffset = getFirstAttributeOffset(); for (int i = readUnsignedShort(currentAttributeOffset - 2); i > 0; --i) { String attributeName = readUTF8(currentAttributeOffset, charBuffer); int attributeLength = readInt(currentAttributeOffset + 2); currentAttributeOffset += 6; sourceFile = readUTF8(currentAttributeOffset, charBuffer); } else if (Constants.INNER_CLASSES.equals(attributeName)) { innerClassesOffset = currentAttributeOffset; enclosingMethodOffset = currentAttributeOffset; } else if (Constants.NEST_HOST.equals(attributeName)) { nestHostClass = readClass(currentAttributeOffset, charBuffer); } else if (Constants.NEST_MEMBERS.equals(attributeName)) { nestMembersOffset = currentAttributeOffset; } else if (Constants.SIGNATURE.equals(attributeName)) { signature = readUTF8(currentAttributeOffset, charBuffer); } else if (Constants.RUNTIME_VISIBLE_ANNOTATIONS.equals(attributeName)) { runtimeVisibleAnnotationsOffset = currentAttributeOffset;
int constantPoolOffset = classReader.getItem(1) - 1; int constantPoolLength = classReader.header - constantPoolOffset; constantPoolCount = classReader.getItemCount(); constantPool = new ByteVector(constantPoolLength); constantPool.putByteArray(inputBytes, constantPoolOffset, constantPoolLength); char[] charBuffer = new char[classReader.getMaxStringLength()]; boolean hasBootstrapMethods = false; int itemIndex = 1; while (itemIndex < constantPoolCount) { int itemOffset = classReader.getItem(itemIndex); int itemTag = inputBytes[itemOffset - 1]; int nameAndTypeItemOffset; case Symbol.CONSTANT_INTERFACE_METHODREF_TAG: nameAndTypeItemOffset = classReader.getItem(classReader.readUnsignedShort(itemOffset + 2)); addConstantMemberReference( itemIndex, itemTag, classReader.readClass(itemOffset, charBuffer), classReader.readUTF8(nameAndTypeItemOffset, charBuffer), classReader.readUTF8(nameAndTypeItemOffset + 2, charBuffer)); break; case Symbol.CONSTANT_INTEGER_TAG: case Symbol.CONSTANT_FLOAT_TAG: addConstantIntegerOrFloat(itemIndex, itemTag, classReader.readInt(itemOffset)); break; case Symbol.CONSTANT_NAME_AND_TYPE_TAG:
int currentAttributeOffset = classReader.getFirstAttributeOffset(); for (int i = classReader.readUnsignedShort(currentAttributeOffset - 2); i > 0; --i) { String attributeName = classReader.readUTF8(currentAttributeOffset, charBuffer); if (Constants.BOOTSTRAP_METHODS.equals(attributeName)) { bootstrapMethodCount = classReader.readUnsignedShort(currentAttributeOffset + 6); break; currentAttributeOffset += 6 + classReader.readInt(currentAttributeOffset + 2); int bootstrapMethodsLength = classReader.readInt(currentAttributeOffset + 2) - 2; bootstrapMethods = new ByteVector(bootstrapMethodsLength); bootstrapMethods.putByteArray(inputBytes, bootstrapMethodsOffset, bootstrapMethodsLength); for (int i = 0; i < bootstrapMethodCount; i++) { int offset = currentOffset - bootstrapMethodsOffset; int bootstrapMethodRef = classReader.readUnsignedShort(currentOffset); currentOffset += 2; int numBootstrapArguments = classReader.readUnsignedShort(currentOffset); currentOffset += 2; int hashCode = classReader.readConst(bootstrapMethodRef, charBuffer).hashCode(); while (numBootstrapArguments-- > 0) { int bootstrapArgument = classReader.readUnsignedShort(currentOffset); currentOffset += 2; hashCode ^= classReader.readConst(bootstrapArgument, charBuffer).hashCode();
int[] typeAnnotationsOffsets = new int[readUnsignedShort(currentOffset)]; currentOffset += 2; int targetType = readInt(currentOffset); switch (targetType >>> 24) { case TypeReference.LOCAL_VARIABLE: int tableLength = readUnsignedShort(currentOffset + 1); currentOffset += 3; while (tableLength-- > 0) { int startPc = readUnsignedShort(currentOffset); int length = readUnsignedShort(currentOffset + 2); createLabel(startPc, context.currentMethodLabels); createLabel(startPc + length, context.currentMethodLabels); int pathLength = readByte(currentOffset); if ((targetType >>> 24) == TypeReference.EXCEPTION_PARAMETER) { String annotationDescriptor = readUTF8(currentOffset, charBuffer); currentOffset += 2; readElementValues( methodVisitor.visitTryCatchAnnotation( targetType & 0xFFFFFF00, path, annotationDescriptor, visible), readElementValues( /* annotationVisitor = */ null, currentOffset, /* named = */ true, charBuffer);
cr = new ClassReader(inputStream); } catch (IOException ioex) { throw new ProxettaException("Unable to inspect super class: " + nextSupername, ioex); cr.accept(new SuperClassVisitor(), 0); if (cr.getInterfaces() != null) { Collections.addAll(allInterfaces, cr.getInterfaces()); try { inputStream = ClassLoaderUtil.getClassAsStream(next, classLoader); cr = new ClassReader(inputStream); cr.accept(new SuperClassVisitor(), 0); if (cr.getInterfaces() != null) { for (String newInterface : cr.getInterfaces()) { if (!allInterfaces.contains(newInterface) && !todoInterfaces.contains(newInterface)) {
int currentOffset = typeAnnotationOffset; int targetType = readInt(typeAnnotationOffset); switch (targetType >>> 24) { case TypeReference.CLASS_TYPE_PARAMETER: case TypeReference.RESOURCE_VARIABLE: targetType &= 0xFF000000; int tableLength = readUnsignedShort(currentOffset + 1); currentOffset += 3; context.currentLocalVariableAnnotationRangeStarts = new Label[tableLength]; context.currentLocalVariableAnnotationRangeIndices = new int[tableLength]; for (int i = 0; i < tableLength; ++i) { int startPc = readUnsignedShort(currentOffset); int length = readUnsignedShort(currentOffset + 2); int index = readUnsignedShort(currentOffset + 4); currentOffset += 6; context.currentLocalVariableAnnotationRangeStarts[i] = createLabel(startPc, context.currentMethodLabels); context.currentLocalVariableAnnotationRangeEnds[i] = createLabel(startPc + length, context.currentMethodLabels); context.currentLocalVariableAnnotationRangeIndices[i] = index; int pathLength = readByte(currentOffset); context.currentTypeAnnotationTargetPath = pathLength == 0 ? null : new TypePath(b, currentOffset);
/** * Checks for all public super methods that are not overridden. */ protected void processSuperMethods() { for (ClassReader cr : targetClassInfo.superClassReaders) { cr.accept(new EmptyClassVisitor() { String declaredClassName; @Override public void visit(final int version, final int access, final String name, final String signature, final String superName, final String[] interfaces) { declaredClassName = name; } @Override public MethodVisitor visitMethod(final int access, final String name, final String desc, final String signature, final String[] exceptions) { if (name.equals(INIT) || name.equals(CLINIT)) { return null; } MethodSignatureVisitor msign = targetClassInfo.lookupMethodSignatureVisitor(access, name, desc, declaredClassName); if (msign == null) { return null; } return applyProxy(msign); } }, 0); } }