下面列出了org.objectweb.asm.Type#METHOD 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
/**
* Produces a {@link MethodHandle} or {@link MethodType} using {@link #targetLoader} for the
* given ASM {@link Handle} or {@link Type}. {@code lookup} is only used for resolving {@link
* Handle}s.
*/
private Object toJvmMetatype(Lookup lookup, Object asm) throws ReflectiveOperationException {
if (asm instanceof Number) {
return asm;
}
if (asm instanceof Type) {
Type type = (Type) asm;
switch (type.getSort()) {
case Type.OBJECT:
return loadFromInternal(type.getInternalName());
case Type.METHOD:
return MethodType.fromMethodDescriptorString(type.getDescriptor(), targetLoader);
default:
throw new IllegalArgumentException("Cannot convert: " + asm);
}
}
if (asm instanceof Handle) {
return toMethodHandle(lookup, (Handle) asm, /*target*/ true);
}
throw new IllegalArgumentException("Cannot convert: " + asm);
}
public static Type unboxType(Object cst) {
Class<?> c = cst.getClass();
Type t = unboxTable.get(c);
if(t == null) {
if(c == Type.class) {
Type type = (Type) cst;
if (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY) {
return Type.getType("Ljava/lang/Class;");
} else if (type.getSort() == Type.METHOD) {
return Type.getType("Ljava/lang/invoke/MethodType;");
} else {
throw new RuntimeException("Invalid type: " + cst);
}
} else {
throw new UnsupportedOperationException(c.getName() + " : " + unboxTable.containsKey(c));
}
} else {
return t;
}
}
Builder addDependency(Type type) {
switch (type.getSort()) {
case Type.OBJECT:
mObservedDependencies.add(type);
break;
case Type.ARRAY:
addDependency(type.getElementType());
break;
case Type.METHOD:
addDependency(type.getReturnType());
for (Type argumentType : type.getArgumentTypes()) {
addDependency(argumentType);
}
break;
default:
break;
}
return this;
}
private void visitType(Type type) {
switch (type.getSort()) {
case Type.ARRAY:
visitType(type.getElementType());
break;
case Type.METHOD:
visitType(type.getReturnType());
visitTypes(type.getArgumentTypes());
break;
case Type.OBJECT:
addReferencedClassName(type.getInternalName());
break;
// $CASES-OMITTED
default:
// Others are primitives or void; don't care
break;
}
}
private Type mapType(Type t) {
switch (t.getSort()) {
case Type.ARRAY:
String s = mapDesc(t.getElementType().getDescriptor());
for (int i = 0; i < t.getDimensions(); ++i) {
s = '[' + s;
}
return Type.getType(s);
case Type.OBJECT:
s = map(t.getInternalName());
return s != null ? Type.getObjectType(s) : t;
case Type.METHOD:
return Type.getMethodType(mapMethodDesc(t.getDescriptor()));
}
return t;
}
/**
* Generates instructions to pop the result of the method off the stack. This will only generate instructions if the method being
* invoked generates a return value.
* @param invokeInsnNode instruction for the method that was invoked (can either be of type {@link MethodInsnNode} or
* {@link InvokeDynamicInsnNode} -- this is used to determine how many items to pop off the stack
* @return instructions for a pop (only if the method being invoked generates a return value)
* @throws IllegalArgumentException if {@code invokeInsnNode} isn't of type {@link MethodInsnNode} or {@link InvokeDynamicInsnNode}
* @throws NullPointerException if any argument is {@code null}
*/
private static InsnList popMethodResult(AbstractInsnNode invokeInsnNode) {
Validate.notNull(invokeInsnNode);
Type returnType = getReturnTypeOfInvocation(invokeInsnNode);
InsnList ret = new InsnList();
switch (returnType.getSort()) {
case Type.LONG:
case Type.DOUBLE:
ret.add(new InsnNode(Opcodes.POP2));
break;
case Type.VOID:
break;
case Type.METHOD:
throw new IllegalStateException(); // this should never happen
default:
ret.add(new InsnNode(Opcodes.POP));
break;
}
return ret;
}
void checkLDCConstant(final Object cst) {
if (cst instanceof Type) {
int s = ((Type) cst).getSort();
if (s != Type.OBJECT && s != Type.ARRAY && s != Type.METHOD) {
throw new IllegalArgumentException("Illegal LDC constant value");
}
if (s != Type.METHOD && (version & 0xFFFF) < Opcodes.V1_5) {
throw new IllegalArgumentException("ldc of a constant class requires at least version 1.5");
}
if (s == Type.METHOD && (version & 0xFFFF) < Opcodes.V1_7) {
throw new IllegalArgumentException("ldc of a method type requires at least version 1.7");
}
} else if (cst instanceof Handle) {
if ((version & 0xFFFF) < Opcodes.V1_7) {
throw new IllegalArgumentException("ldc of a handle requires at least version 1.7");
}
int tag = ((Handle) cst).getTag();
if (tag < Opcodes.H_GETFIELD || tag > Opcodes.H_INVOKEINTERFACE) {
throw new IllegalArgumentException("invalid handle tag " + tag);
}
} else {
checkConstant(cst);
}
}
@Override
public void visit(final String name, final Object value) {
checkVisitEndNotCalled();
checkName(name);
if (!(value instanceof Byte
|| value instanceof Boolean
|| value instanceof Character
|| value instanceof Short
|| value instanceof Integer
|| value instanceof Long
|| value instanceof Float
|| value instanceof Double
|| value instanceof String
|| value instanceof Type
|| value instanceof byte[]
|| value instanceof boolean[]
|| value instanceof char[]
|| value instanceof short[]
|| value instanceof int[]
|| value instanceof long[]
|| value instanceof float[]
|| value instanceof double[])) {
throw new IllegalArgumentException("Invalid annotation value");
}
if (value instanceof Type && ((Type) value).getSort() == Type.METHOD) {
throw new IllegalArgumentException("Invalid annotation value");
}
super.visit(name, value);
}
@Override
public void visitLdcInsn(final Object value) {
super.visitLdcInsn(value);
if (this.locals == null) {
labels = null;
return;
}
if (value instanceof Integer) {
push(Opcodes.INTEGER);
} else if (value instanceof Long) {
push(Opcodes.LONG);
push(Opcodes.TOP);
} else if (value instanceof Float) {
push(Opcodes.FLOAT);
} else if (value instanceof Double) {
push(Opcodes.DOUBLE);
push(Opcodes.TOP);
} else if (value instanceof String) {
push("java/lang/String");
} else if (value instanceof Type) {
int sort = ((Type) value).getSort();
if (sort == Type.OBJECT || sort == Type.ARRAY) {
push("java/lang/Class");
} else if (sort == Type.METHOD) {
push("java/lang/invoke/MethodType");
} else {
throw new IllegalArgumentException();
}
} else if (value instanceof Handle) {
push("java/lang/invoke/MethodHandle");
} else if (value instanceof ConstantDynamic) {
pushDescriptor(((ConstantDynamic) value).getDescriptor());
} else {
throw new IllegalArgumentException();
}
labels = null;
}
@Override
public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, Object... bsmArgs) {
StringBuilder buf = stringBuilder;
buf.setLength(0);
buf.append(tab2).append("INVOKEDYNAMIC").append(' ').append(name);
appendDescriptor(METHOD_DESCRIPTOR, desc);
if (bsmArgs.length != 0) {
buf.append(" [");
for (int i = 0; i < bsmArgs.length; ++i) {
Object arg = bsmArgs[i];
if (arg instanceof String) {
appendString(buf, (String) arg);
} else if (arg instanceof Type) {
Type type = (Type) arg;
if (type.getSort() == Type.METHOD) {
appendDescriptor(METHOD_DESCRIPTOR, type.getDescriptor());
} else {
appendDescriptor(INTERNAL_NAME, type.getDescriptor());
}
} else if (arg instanceof Handle) {
Handle handle = (Handle) arg;
appendDescriptor(HANDLE_DESCRIPTOR, getMethodDescriptor(handle.getDesc()));
} else {
buf.append(arg);
}
if (i + 1 < bsmArgs.length) {
buf.append(", ");
}
}
buf.append(']');
}
buf.append('\n');
text.add(buf.toString());
}
@Override
public void visitLdcInsn(final Object value) {
super.visitLdcInsn(value);
if (this.locals == null) {
labels = null;
return;
}
if (value instanceof Integer) {
push(Opcodes.INTEGER);
} else if (value instanceof Long) {
push(Opcodes.LONG);
push(Opcodes.TOP);
} else if (value instanceof Float) {
push(Opcodes.FLOAT);
} else if (value instanceof Double) {
push(Opcodes.DOUBLE);
push(Opcodes.TOP);
} else if (value instanceof String) {
push("java/lang/String");
} else if (value instanceof Type) {
int sort = ((Type) value).getSort();
if (sort == Type.OBJECT || sort == Type.ARRAY) {
push("java/lang/Class");
} else if (sort == Type.METHOD) {
push("java/lang/invoke/MethodType");
} else {
throw new IllegalArgumentException();
}
} else if (value instanceof Handle) {
push("java/lang/invoke/MethodHandle");
} else if (value instanceof ConstantDynamic) {
pushDescriptor(((ConstantDynamic) value).getDescriptor());
} else {
throw new IllegalArgumentException();
}
labels = null;
}
@Override
public void visit(final String name, final Object value) {
checkVisitEndNotCalled();
checkName(name);
if (!(value instanceof Byte
|| value instanceof Boolean
|| value instanceof Character
|| value instanceof Short
|| value instanceof Integer
|| value instanceof Long
|| value instanceof Float
|| value instanceof Double
|| value instanceof String
|| value instanceof Type
|| value instanceof byte[]
|| value instanceof boolean[]
|| value instanceof char[]
|| value instanceof short[]
|| value instanceof int[]
|| value instanceof long[]
|| value instanceof float[]
|| value instanceof double[])) {
throw new IllegalArgumentException("Invalid annotation value");
}
if (value instanceof Type && ((Type) value).getSort() == Type.METHOD) {
throw new IllegalArgumentException("Invalid annotation value");
}
super.visit(name, value);
}
private void addType(final Type type) {
switch (type.getSort()) {
case Type.ARRAY:
addType(type.getElementType());
break;
case Type.OBJECT:
addPackage(type.getInternalName());
break;
case Type.METHOD:
addMethodTypes(type.getDescriptor());
break;
default:
}
}
/**
* Convert a Type sort to a string representation.
*
* @param sort
* Type sort value.
*
* @return Sort string value.
*/
public static String sortToString(int sort) {
switch(sort) {
case Type.VOID:
return "VOID";
case Type.BOOLEAN:
return "BOOLEAN";
case Type.CHAR:
return "CHAR";
case Type.BYTE:
return "BYTE";
case Type.SHORT:
return "SHORT";
case Type.INT:
return "INT";
case Type.FLOAT:
return "FLOAT";
case Type.LONG:
return "LONG";
case Type.DOUBLE:
return "DOUBLE";
case Type.ARRAY:
return "ARRAY";
case Type.OBJECT:
return "OBJECT";
case Type.METHOD:
return "METHOD";
case INTERNAL:
return "INTERNAL";
default:
return "UNKNOWN";
}
}
public void trackType(Type type) {
switch (type.getSort()) {
case Type.BOOLEAN:
case Type.BYTE:
case Type.CHAR:
case Type.SHORT:
case Type.INT:
intFound = true;
break;
case Type.LONG:
longFound = true;
break;
case Type.FLOAT:
floatFound = true;
break;
case Type.DOUBLE:
doubleFound = true;
break;
case Type.OBJECT:
case Type.ARRAY:
objectFound = true;
break;
case Type.VOID:
case Type.METHOD:
default:
throw new IllegalArgumentException(); // this should never happen
}
}
@Override
public BasicValue newOperation(final AbstractInsnNode insn) throws AnalyzerException {
switch (insn.getOpcode()) {
case ACONST_NULL:
return newValue(NULL_TYPE);
case ICONST_M1:
case ICONST_0:
case ICONST_1:
case ICONST_2:
case ICONST_3:
case ICONST_4:
case ICONST_5:
return BasicValue.INT_VALUE;
case LCONST_0:
case LCONST_1:
return BasicValue.LONG_VALUE;
case FCONST_0:
case FCONST_1:
case FCONST_2:
return BasicValue.FLOAT_VALUE;
case DCONST_0:
case DCONST_1:
return BasicValue.DOUBLE_VALUE;
case BIPUSH:
case SIPUSH:
return BasicValue.INT_VALUE;
case LDC:
Object value = ((LdcInsnNode) insn).cst;
if (value instanceof Integer) {
return BasicValue.INT_VALUE;
} else if (value instanceof Float) {
return BasicValue.FLOAT_VALUE;
} else if (value instanceof Long) {
return BasicValue.LONG_VALUE;
} else if (value instanceof Double) {
return BasicValue.DOUBLE_VALUE;
} else if (value instanceof String) {
return newValue(Type.getObjectType("java/lang/String"));
} else if (value instanceof Type) {
int sort = ((Type) value).getSort();
if (sort == Type.OBJECT || sort == Type.ARRAY) {
return newValue(Type.getObjectType("java/lang/Class"));
} else if (sort == Type.METHOD) {
return newValue(Type.getObjectType("java/lang/invoke/MethodType"));
} else {
throw new AnalyzerException(insn, "Illegal LDC value " + value);
}
} else if (value instanceof Handle) {
return newValue(Type.getObjectType("java/lang/invoke/MethodHandle"));
} else if (value instanceof ConstantDynamic) {
return newValue(Type.getType(((ConstantDynamic) value).getDescriptor()));
} else {
throw new AnalyzerException(insn, "Illegal LDC value " + value);
}
case JSR:
return BasicValue.RETURNADDRESS_VALUE;
case GETSTATIC:
return newValue(Type.getType(((FieldInsnNode) insn).desc));
case NEW:
return newValue(Type.getObjectType(((TypeInsnNode) insn).desc));
default:
throw new AssertionError();
}
}
@Override
public CoffeeValue newOperation(final AbstractInsnNode insn) throws AnalyzerException {
switch (insn.getOpcode()) {
case ACONST_NULL:
return newValue(NULL_TYPE);
case ICONST_M1:
case ICONST_0:
case ICONST_1:
case ICONST_2:
case ICONST_3:
case ICONST_4:
case ICONST_5:
return CoffeeValue.INT_VALUE;
case LCONST_0:
case LCONST_1:
return CoffeeValue.LONG_VALUE;
case FCONST_0:
case FCONST_1:
case FCONST_2:
return CoffeeValue.FLOAT_VALUE;
case DCONST_0:
case DCONST_1:
return CoffeeValue.DOUBLE_VALUE;
case BIPUSH:
case SIPUSH:
return CoffeeValue.INT_VALUE;
case LDC:
Object value = ((LdcInsnNode) insn).cst;
if (value instanceof Integer) {
return CoffeeValue.INT_VALUE;
} else if (value instanceof Float) {
return CoffeeValue.FLOAT_VALUE;
} else if (value instanceof Long) {
return CoffeeValue.LONG_VALUE;
} else if (value instanceof Double) {
return CoffeeValue.DOUBLE_VALUE;
} else if (value instanceof String) {
return newValue(Type.getObjectType("java/lang/String"));
} else if (value instanceof Type) {
int sort = ((Type) value).getSort();
if (sort == Type.OBJECT || sort == Type.ARRAY) {
return newValue(Type.getObjectType("java/lang/Class"));
} else if (sort == Type.METHOD) {
return newValue(Type.getObjectType("java/lang/invoke/MethodType"));
} else {
throw new AnalyzerException(insn, "Illegal LDC value " + value);
}
} else if (value instanceof Handle) {
return newValue(Type.getObjectType("java/lang/invoke/MethodHandle"));
} else if (value instanceof ConstantDynamic) {
return newValue(Type.getType(((ConstantDynamic) value).getDescriptor()));
} else {
throw new AnalyzerException(insn, "Illegal LDC value " + value);
}
case JSR:
return CoffeeValue.RETURNADDRESS_VALUE; // missing implementation
case GETSTATIC:
return newValue(Type.getType(((FieldInsnNode) insn).desc));
case NEW:
return newValue(Type.getObjectType(((TypeInsnNode) insn).desc));
default:
throw new AssertionError();
}
}
/**
* Checks that the given value is a valid operand for the LDC instruction.
*
* @param value the value to be checked.
*/
private void checkLdcConstant(final Object value) {
if (value instanceof Type) {
int sort = ((Type) value).getSort();
if (sort != Type.OBJECT && sort != Type.ARRAY && sort != Type.METHOD) {
throw new IllegalArgumentException("Illegal LDC constant value");
}
if (sort != Type.METHOD && (version & 0xFFFF) < Opcodes.V1_5) {
throw new IllegalArgumentException("ldc of a constant class requires at least version 1.5");
}
if (sort == Type.METHOD && (version & 0xFFFF) < Opcodes.V1_7) {
throw new IllegalArgumentException("ldc of a method type requires at least version 1.7");
}
} else if (value instanceof Handle) {
if ((version & 0xFFFF) < Opcodes.V1_7) {
throw new IllegalArgumentException("ldc of a Handle requires at least version 1.7");
}
Handle handle = (Handle) value;
int tag = handle.getTag();
if (tag < Opcodes.H_GETFIELD || tag > Opcodes.H_INVOKEINTERFACE) {
throw new IllegalArgumentException("invalid handle tag " + tag);
}
checkInternalName(this.version, handle.getOwner(), "handle owner");
if (tag <= Opcodes.H_PUTSTATIC) {
checkDescriptor(this.version, handle.getDesc(), false);
} else {
checkMethodDescriptor(this.version, handle.getDesc());
}
String handleName = handle.getName();
if (!("<init>".equals(handleName) && tag == Opcodes.H_NEWINVOKESPECIAL)) {
checkMethodIdentifier(this.version, handleName, "handle name");
}
} else if (value instanceof ConstantDynamic) {
if ((version & 0xFFFF) < Opcodes.V11) {
throw new IllegalArgumentException("ldc of a ConstantDynamic requires at least version 11");
}
ConstantDynamic constantDynamic = (ConstantDynamic) value;
checkMethodIdentifier(this.version, constantDynamic.getName(), "constant dynamic name");
checkDescriptor(this.version, constantDynamic.getDescriptor(), false);
checkLdcConstant(constantDynamic.getBootstrapMethod());
int bootstrapMethodArgumentCount = constantDynamic.getBootstrapMethodArgumentCount();
for (int i = 0; i < bootstrapMethodArgumentCount; ++i) {
checkLdcConstant(constantDynamic.getBootstrapMethodArgument(i));
}
} else {
checkConstant(value);
}
}
public static Type computeType(Object cst) {
if (cst == null) {
return Type.getType("Ljava/lang/Object;");
} else if (cst instanceof Integer) {
int val = ((Integer) cst).intValue();
if (val >= Byte.MIN_VALUE && val <= Byte.MAX_VALUE) {
return Type.BYTE_TYPE;
} else if (val >= Short.MIN_VALUE && val <= Short.MAX_VALUE) {
return Type.SHORT_TYPE;
} else {
return Type.INT_TYPE;
}
// return Type.INT_TYPE;
} else if (cst instanceof Long) {
return Type.LONG_TYPE;
} else if (cst instanceof Float) {
return Type.FLOAT_TYPE;
} else if (cst instanceof Double) {
return Type.DOUBLE_TYPE;
} else if (cst instanceof String) {
return Type.getType("Ljava/lang/String;");
} else if (cst instanceof Type) {
Type type = (Type) cst;
if (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY) {
return Type.getType("Ljava/lang/Class;");
} else if (type.getSort() == Type.METHOD) {
return Type.getType("Ljava/lang/invoke/MethodType;");
} else {
throw new RuntimeException("Invalid type: " + cst);
}
} else if (cst instanceof Handle) {
return Type.getType("Ljava/lang/invoke/MethodHandle;");
} else if (cst instanceof Boolean) {
return Type.BOOLEAN_TYPE;
} else if(cst instanceof Byte) {
return Type.BYTE_TYPE;
} else if (cst instanceof Character) {
return Type.CHAR_TYPE;
} else if(cst instanceof Short) {
return Type.SHORT_TYPE;
} else {
throw new RuntimeException("Invalid type: " + cst);
}
}
/**
* Checks that the given value is a valid operand for the LDC instruction.
*
* @param value the value to be checked.
*/
private void checkLdcConstant(final Object value) {
if (value instanceof Type) {
int sort = ((Type) value).getSort();
if (sort != Type.OBJECT && sort != Type.ARRAY && sort != Type.METHOD) {
throw new IllegalArgumentException("Illegal LDC constant value");
}
if (sort != Type.METHOD && (version & 0xFFFF) < Opcodes.V1_5) {
throw new IllegalArgumentException("ldc of a constant class requires at least version 1.5");
}
if (sort == Type.METHOD && (version & 0xFFFF) < Opcodes.V1_7) {
throw new IllegalArgumentException("ldc of a method type requires at least version 1.7");
}
} else if (value instanceof Handle) {
if ((version & 0xFFFF) < Opcodes.V1_7) {
throw new IllegalArgumentException("ldc of a Handle requires at least version 1.7");
}
Handle handle = (Handle) value;
int tag = handle.getTag();
if (tag < Opcodes.H_GETFIELD || tag > Opcodes.H_INVOKEINTERFACE) {
throw new IllegalArgumentException("invalid handle tag " + tag);
}
checkInternalName(this.version, handle.getOwner(), "handle owner");
if (tag <= Opcodes.H_PUTSTATIC) {
checkDescriptor(this.version, handle.getDesc(), false);
} else {
checkMethodDescriptor(this.version, handle.getDesc());
}
String handleName = handle.getName();
if (!("<init>".equals(handleName) && tag == Opcodes.H_NEWINVOKESPECIAL)) {
checkMethodIdentifier(this.version, handleName, "handle name");
}
} else if (value instanceof ConstantDynamic) {
if ((version & 0xFFFF) < Opcodes.V11) {
throw new IllegalArgumentException("ldc of a ConstantDynamic requires at least version 11");
}
ConstantDynamic constantDynamic = (ConstantDynamic) value;
checkMethodIdentifier(this.version, constantDynamic.getName(), "constant dynamic name");
checkDescriptor(this.version, constantDynamic.getDescriptor(), false);
checkLdcConstant(constantDynamic.getBootstrapMethod());
int bootstrapMethodArgumentCount = constantDynamic.getBootstrapMethodArgumentCount();
for (int i = 0; i < bootstrapMethodArgumentCount; ++i) {
checkLdcConstant(constantDynamic.getBootstrapMethodArgument(i));
}
} else {
checkConstant(value);
}
}