private void doVisitMethodInsn( int opcode, final String owner, final String name, final String desc, final boolean itf) { checkStartCode(); checkEndCode(); checkOpcode(opcode, 5); if (opcode != Opcodes.INVOKESPECIAL || !"<init>".equals(name)) { checkMethodIdentifier(version, name, "name"); } checkInternalName(owner, "owner"); checkMethodDesc(desc); if (opcode == Opcodes.INVOKEVIRTUAL && itf) { throw new IllegalArgumentException("INVOKEVIRTUAL can't be used with interfaces"); } if (opcode == Opcodes.INVOKEINTERFACE && !itf) { throw new IllegalArgumentException("INVOKEINTERFACE can't be used with classes"); } // Calling super.visitMethodInsn requires to call the correct version // depending on this.api (otherwise infinite loops can occur). To // simplify and to make it easier to automatically remove the backward // compatibility code, we inline the code of the overridden method here. if (mv != null) { mv.visitMethodInsn(opcode, owner, name, desc, itf); } ++insnCount; }
@Override public void visitLdcInsn(final Object cst) { checkStartCode(); checkEndCode(); checkLDCConstant(cst); super.visitLdcInsn(cst); ++insnCount; }
@Override public void visitLineNumber(final int line, final Label start) { checkStartCode(); checkEndCode(); checkUnsignedShort(line, "Invalid line number"); checkLabel(start, true, "start label"); super.visitLineNumber(line, start); }
@Override public void visitInsn(final int opcode) { checkStartCode(); checkEndCode(); checkOpcode(opcode, 0); super.visitInsn(opcode); ++insnCount; }
@Override public void visitVarInsn(final int opcode, final int var) { checkStartCode(); checkEndCode(); checkOpcode(opcode, 2); checkUnsignedShort(var, "Invalid variable index"); super.visitVarInsn(opcode, var); ++insnCount; }
@Override public void visitIincInsn(final int var, final int increment) { checkStartCode(); checkEndCode(); checkUnsignedShort(var, "Invalid variable index"); checkSignedShort(increment, "Invalid increment"); super.visitIincInsn(var, increment); ++insnCount; }
@Override public void visitLabel(final Label label) { checkStartCode(); checkEndCode(); checkLabel(label, false, "label"); if (labels.get(label) != null) { throw new IllegalArgumentException("Already visited label"); } labels.put(label, insnCount); super.visitLabel(label); }
@Override public void visitJumpInsn(final int opcode, final Label label) { checkStartCode(); checkEndCode(); checkOpcode(opcode, 6); checkLabel(label, false, "label"); checkNonDebugLabel(label); super.visitJumpInsn(opcode, label); usedLabels.add(label); ++insnCount; }
@Override public void visitTypeInsn(final int opcode, final String type) { checkStartCode(); checkEndCode(); checkOpcode(opcode, 3); checkInternalName(type, "type"); if (opcode == Opcodes.NEW && type.charAt(0) == '[') { throw new IllegalArgumentException("NEW cannot be used to create arrays: " + type); } super.visitTypeInsn(opcode, type); ++insnCount; }
@Override public void visitFieldInsn( final int opcode, final String owner, final String name, final String desc) { checkStartCode(); checkEndCode(); checkOpcode(opcode, 4); checkInternalName(owner, "owner"); checkUnqualifiedName(version, name, "name"); checkDesc(desc, false); super.visitFieldInsn(opcode, owner, name, desc); ++insnCount; }
@Override public AnnotationVisitor visitTryCatchAnnotation( final int typeRef, final TypePath typePath, final String desc, final boolean visible) { checkStartCode(); checkEndCode(); int sort = typeRef >>> 24; if (sort != TypeReference.EXCEPTION_PARAMETER) { throw new IllegalArgumentException( "Invalid type reference sort 0x" + Integer.toHexString(sort)); } CheckClassAdapter.checkTypeRefAndPath(typeRef, typePath); CheckMethodAdapter.checkDesc(desc, false); return new CheckAnnotationAdapter( super.visitTryCatchAnnotation(typeRef, typePath, desc, visible)); }
@Override public void visitMultiANewArrayInsn(final String desc, final int dims) { checkStartCode(); checkEndCode(); checkDesc(desc, false); if (desc.charAt(0) != '[') { throw new IllegalArgumentException( "Invalid descriptor (must be an array type descriptor): " + desc); } if (dims < 1) { throw new IllegalArgumentException("Invalid dimensions (must be greater than 0): " + dims); } if (dims > desc.lastIndexOf('[') + 1) { throw new IllegalArgumentException( "Invalid dimensions (must not be greater than dims(desc)): " + dims); } super.visitMultiANewArrayInsn(desc, dims); ++insnCount; }
@Override public void visitLookupSwitchInsn(final Label dflt, final int[] keys, final Label[] labels) { checkEndCode(); checkStartCode(); checkLabel(dflt, false, "default label"); checkNonDebugLabel(dflt); if (keys == null || labels == null || keys.length != labels.length) { throw new IllegalArgumentException("There must be the same number of keys and labels"); } for (int i = 0; i < labels.length; ++i) { checkLabel(labels[i], false, "label at index " + i); checkNonDebugLabel(labels[i]); } super.visitLookupSwitchInsn(dflt, keys, labels); usedLabels.add(dflt); for (int i = 0; i < labels.length; ++i) { usedLabels.add(labels[i]); } ++insnCount; }
@Override public void visitTryCatchBlock( final Label start, final Label end, final Label handler, final String type) { checkStartCode(); checkEndCode(); checkLabel(start, false, "start label"); checkLabel(end, false, "end label"); checkLabel(handler, false, "handler label"); checkNonDebugLabel(start); checkNonDebugLabel(end); checkNonDebugLabel(handler); if (labels.get(start) != null || labels.get(end) != null || labels.get(handler) != null) { throw new IllegalStateException("Try catch blocks must be visited before their labels"); } if (type != null) { checkInternalName(type, "type"); } super.visitTryCatchBlock(start, end, handler, type); handlers.add(start); handlers.add(end); }
@Override public AnnotationVisitor visitLocalVariableAnnotation( int typeRef, TypePath typePath, Label[] start, Label[] end, int[] index, String desc, boolean visible) { checkStartCode(); checkEndCode(); int sort = typeRef >>> 24; if (sort != TypeReference.LOCAL_VARIABLE && sort != TypeReference.RESOURCE_VARIABLE) { throw new IllegalArgumentException( "Invalid type reference sort 0x" + Integer.toHexString(sort)); } CheckClassAdapter.checkTypeRefAndPath(typeRef, typePath); checkDesc(desc, false); if (start == null || end == null || index == null || end.length != start.length || index.length != start.length) { throw new IllegalArgumentException( "Invalid start, end and index arrays (must be non null and of identical length"); } for (int i = 0; i < start.length; ++i) { checkLabel(start[i], true, "start label"); checkLabel(end[i], true, "end label"); checkUnsignedShort(index[i], "Invalid variable index"); int s = labels.get(start[i]).intValue(); int e = labels.get(end[i]).intValue(); if (e < s) { throw new IllegalArgumentException( "Invalid start and end labels (end must be greater than start)"); } } return super.visitLocalVariableAnnotation(typeRef, typePath, start, end, index, desc, visible); }
@Override public AnnotationVisitor visitInsnAnnotation( final int typeRef, final TypePath typePath, final String desc, final boolean visible) { checkStartCode(); checkEndCode(); int sort = typeRef >>> 24; if (sort != TypeReference.INSTANCEOF && sort != TypeReference.NEW && sort != TypeReference.CONSTRUCTOR_REFERENCE && sort != TypeReference.METHOD_REFERENCE && sort != TypeReference.CAST && sort != TypeReference.CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT && sort != TypeReference.METHOD_INVOCATION_TYPE_ARGUMENT && sort != TypeReference.CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT && sort != TypeReference.METHOD_REFERENCE_TYPE_ARGUMENT) { throw new IllegalArgumentException( "Invalid type reference sort 0x" + Integer.toHexString(sort)); } CheckClassAdapter.checkTypeRefAndPath(typeRef, typePath); CheckMethodAdapter.checkDesc(desc, false); return new CheckAnnotationAdapter(super.visitInsnAnnotation(typeRef, typePath, desc, visible)); }
@Override public void visitIntInsn(final int opcode, final int operand) { checkStartCode(); checkEndCode(); checkOpcode(opcode, 1); switch (opcode) { case Opcodes.BIPUSH: checkSignedByte(operand, "Invalid operand"); break; case Opcodes.SIPUSH: checkSignedShort(operand, "Invalid operand"); break; // case Constants.NEWARRAY: default: if (operand < Opcodes.T_BOOLEAN || operand > Opcodes.T_LONG) { throw new IllegalArgumentException( "Invalid operand (must be an array type code T_...): " + operand); } } super.visitIntInsn(opcode, operand); ++insnCount; }
@Override public void visitLocalVariable( final String name, final String desc, final String signature, final Label start, final Label end, final int index) { checkStartCode(); checkEndCode(); checkUnqualifiedName(version, name, "name"); checkDesc(desc, false); checkLabel(start, true, "start label"); checkLabel(end, true, "end label"); checkUnsignedShort(index, "Invalid variable index"); int s = labels.get(start).intValue(); int e = labels.get(end).intValue(); if (e < s) { throw new IllegalArgumentException( "Invalid start and end labels (end must be greater than start)"); } super.visitLocalVariable(name, desc, signature, start, end, index); }
@Override public void visitMaxs(final int maxStack, final int maxLocals) { checkStartCode(); checkEndCode(); endCode = true; for (Label l : usedLabels) { if (labels.get(l) == null) { throw new IllegalStateException("Undefined label used"); } } for (int i = 0; i < handlers.size(); ) { Integer start = labels.get(handlers.get(i++)); Integer end = labels.get(handlers.get(i++)); if (start == null || end == null) { throw new IllegalStateException("Undefined try catch block labels"); } if (end.intValue() <= start.intValue()) { throw new IllegalStateException("Emty try catch block handler range"); } } checkUnsignedShort(maxStack, "Invalid max stack"); checkUnsignedShort(maxLocals, "Invalid max locals"); super.visitMaxs(maxStack, maxLocals); }
@Override public void visitTableSwitchInsn( final int min, final int max, final Label dflt, final Label... labels) { checkStartCode(); checkEndCode(); if (max < min) { throw new IllegalArgumentException( "Max = " + max + " must be greater than or equal to min = " + min); } checkLabel(dflt, false, "default label"); checkNonDebugLabel(dflt); if (labels == null || labels.length != max - min + 1) { throw new IllegalArgumentException("There must be max - min + 1 labels"); } for (int i = 0; i < labels.length; ++i) { checkLabel(labels[i], false, "label at index " + i); checkNonDebugLabel(labels[i]); } super.visitTableSwitchInsn(min, max, dflt, labels); for (int i = 0; i < labels.length; ++i) { usedLabels.add(labels[i]); } ++insnCount; }
@Override public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, Object... bsmArgs) { checkStartCode(); checkEndCode(); checkMethodIdentifier(version, name, "name"); checkMethodDesc(desc); if (bsm.getTag() != Opcodes.H_INVOKESTATIC && bsm.getTag() != Opcodes.H_NEWINVOKESPECIAL) { throw new IllegalArgumentException("invalid handle tag " + bsm.getTag()); } for (int i = 0; i < bsmArgs.length; i++) { checkLDCConstant(bsmArgs[i]); } super.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs); ++insnCount; }