下面列出了org.objectweb.asm.Type#VOID 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
public Variable getReturnCacheVar(Type type) {
Validate.notNull(type);
switch (type.getSort()) {
case Type.BOOLEAN:
case Type.BYTE:
case Type.CHAR:
case Type.SHORT:
case Type.INT:
return getIntReturnCacheVar();
case Type.LONG:
return getLongReturnCacheVar();
case Type.FLOAT:
return getFloatReturnCacheVar();
case Type.DOUBLE:
return getDoubleReturnCacheVar();
case Type.ARRAY:
case Type.OBJECT:
return getObjectReturnCacheVar();
case Type.VOID:
return null;
default:
throw new IllegalArgumentException("Bad type");
}
}
@Override
// Override this method to get unmasked type from BasicInterpreter
public BasicValue newValue(final Type type) {
if (type == null) {
return BasicValue.UNINITIALIZED_VALUE;
}
switch (type.getSort()) {
case Type.VOID:
return null;
case Type.BOOLEAN:
case Type.CHAR:
case Type.BYTE:
case Type.SHORT:
case Type.INT:
case Type.FLOAT:
case Type.LONG:
case Type.DOUBLE:
case Type.ARRAY:
case Type.OBJECT:
return new BasicValue(type);
default:
throw new AssertionError();
}
}
private void pushDefault(Type type) {
switch (type.getSort()) {
case Type.VOID:
break;
case Type.DOUBLE:
mv.visitInsn(DCONST_0);
break;
case Type.LONG:
mv.visitInsn(LCONST_0);
break;
case Type.FLOAT:
mv.visitInsn(FCONST_0);
break;
case Type.OBJECT:
case Type.ARRAY:
mv.visitInsn(ACONST_NULL);
break;
default:
mv.visitInsn(ICONST_0);
break;
}
}
@Override
public boolean isPrimitive() {
switch (type.getSort()) {
case Type.ARRAY:
case Type.OBJECT:
case Type.VOID:
case Type.METHOD:
return false;
case Type.BOOLEAN:
case Type.SHORT:
case Type.INT:
case Type.CHAR:
case Type.FLOAT:
case Type.LONG:
case Type.DOUBLE:
return true;
default:
throw new UnsupportedOperationException("Unknown JVM type: " + type);
}
}
private void initOnBeforeAdvice(PointcutClass adviceClass, PointcutMethod adviceMethod)
throws AdviceConstructionException {
checkState(!hasOnBeforeAdvice, "@Pointcut '" + adviceClass.type().getClassName()
+ "' has more than one @OnBefore method");
Method asmMethod = adviceMethod.toAsmMethod();
builder.onBeforeAdvice(asmMethod);
List<AdviceParameter> parameters =
getAdviceParameters(adviceMethod.parameterAnnotationTypes(),
asmMethod.getArgumentTypes(), onBeforeBindAnnotationTypes, OnBeforeType);
builder.addAllOnBeforeParameters(parameters);
if (asmMethod.getReturnType().getSort() != Type.VOID) {
builder.travelerType(asmMethod.getReturnType());
}
checkForBindThreadContext(parameters);
checkForBindOptionalThreadContext(parameters);
hasOnBeforeAdvice = true;
}
/**
* Get the source code name for the specified type
*
* @param type Type to generate a friendly name for
* @param box True to return the equivalent boxing type for primitives
* @param fullyQualified fully-qualify class names
* @return String representation of the specified type, eg "int" for an
* integer primitive or "String" for java.lang.String
*/
public static String getTypeName(Type type, boolean box, boolean fullyQualified) {
if (type == null) {
return "{null?}";
}
switch (type.getSort()) {
case Type.VOID: return box ? "Void" : "void";
case Type.BOOLEAN: return box ? "Boolean" : "boolean";
case Type.CHAR: return box ? "Character" : "char";
case Type.BYTE: return box ? "Byte" : "byte";
case Type.SHORT: return box ? "Short" : "short";
case Type.INT: return box ? "Integer" : "int";
case Type.FLOAT: return box ? "Float" : "float";
case Type.LONG: return box ? "Long" : "long";
case Type.DOUBLE: return box ? "Double" : "double";
case Type.ARRAY: return SignaturePrinter.getTypeName(type.getElementType(), box, fullyQualified) + SignaturePrinter.arraySuffix(type);
case Type.OBJECT:
String typeName = type.getClassName();
if (!fullyQualified) {
typeName = typeName.substring(typeName.lastIndexOf('.') + 1);
}
return typeName;
default:
return "Object";
}
}
private static Class<?> getType(Type type) throws ClassNotFoundException {
switch (type.getSort()) {
case Type.VOID:
return void.class;
case Type.BOOLEAN:
return boolean.class;
case Type.CHAR:
return char.class;
case Type.BYTE:
return byte.class;
case Type.SHORT:
return short.class;
case Type.INT:
return int.class;
case Type.FLOAT:
return float.class;
case Type.LONG:
return long.class;
case Type.DOUBLE:
return double.class;
case Type.ARRAY:
return Util.getArrayClass(getType(type.getElementType()),
type.getDimensions());
default:
return Class.forName(type.getClassName(), false, null);
}
}
@Override
public CoffeeValue newValue(final Type type) {
if (type == null) {
return CoffeeValue.UNINITIALIZED_VALUE;
}
switch (type.getSort()) {
case Type.VOID:
return null;
case Type.BOOLEAN:
case Type.CHAR:
case Type.BYTE:
case Type.SHORT:
case Type.INT:
return CoffeeValue.INT_VALUE;
case Type.FLOAT:
return CoffeeValue.FLOAT_VALUE;
case Type.LONG:
return CoffeeValue.LONG_VALUE;
case Type.DOUBLE:
return CoffeeValue.DOUBLE_VALUE;
case Type.ARRAY:
case Type.OBJECT:
return new CoffeeValue(type);
default:
throw new AssertionError();
}
}
@Override
public BasicValue newValue(final Type type)
{
if(type == null)
return new BasicValue(Type.getType("java/lang/Object"));
switch(type.getSort())
{
case Type.VOID:
return null;
case Type.BOOLEAN:
case Type.CHAR:
case Type.BYTE:
case Type.SHORT:
case Type.INT:
return BasicValue.INT_VALUE;
case Type.FLOAT:
return BasicValue.FLOAT_VALUE;
case Type.LONG:
return BasicValue.LONG_VALUE;
case Type.DOUBLE:
return BasicValue.DOUBLE_VALUE;
case Type.ARRAY:
case Type.OBJECT:
return new BasicValue(type);
default:
throw new Error("Internal error");
}
}
@Override
public void generate(CodeEmitter code) {
// VOID, BOOLEAN, CHAR, BYTE, SHORT, INT, FLOAT, LONG, DOUBLE, ARRAY, OBJECT or METHOD.
int opcode;
switch (getType().getJVMType().getSort()) {
case Type.VOID:
case Type.METHOD:
throw new UnsupportedOperationException("Unsupported NullExpr type: " + getType());
case Type.BOOLEAN:
case Type.SHORT:
case Type.INT:
case Type.CHAR:
opcode = Opcodes.ICONST_0;
break;
case Type.FLOAT:
opcode = Opcodes.FCONST_0;
break;
case Type.LONG:
opcode = Opcodes.LCONST_0;
break;
case Type.DOUBLE:
opcode = Opcodes.DCONST_0;
break;
case Type.ARRAY:
case Type.OBJECT:
opcode = Opcodes.ACONST_NULL;
break;
default:
throw new UnsupportedOperationException("Unknown NullExpr type: " + getType());
}
code.getMethodVisitor().visitInsn(opcode);
if (opcode == Opcodes.ACONST_NULL) {
code.cast(getType(), AnyTypeWidget.getInstance());
}
}
private boolean willPushAll(AbstractInsnNode ain)
{
if(ain.getOpcode() == Opcodes.INVOKESTATIC && Type.getArgumentTypes(((MethodInsnNode)ain).desc).length == 0
&& Type.getReturnType(((MethodInsnNode)ain).desc).getSort() != Type.VOID
&& Type.getReturnType(((MethodInsnNode)ain).desc).getSort() != Type.LONG
&& Type.getReturnType(((MethodInsnNode)ain).desc).getSort() != Type.DOUBLE)
return true;
if(ain.getOpcode() == Opcodes.GETSTATIC && Type.getType(((FieldInsnNode)ain).desc).getSort() != Type.VOID
&& Type.getType(((FieldInsnNode)ain).desc).getSort() != Type.LONG
&& Type.getType(((FieldInsnNode)ain).desc).getSort() != Type.DOUBLE)
return true;
return willPush(ain);
}
private static int doMethodEmulation(String desc) {
int result = 0;
Type returnType = Type.getReturnType(desc);
if (returnType.getSort() == Type.LONG || returnType.getSort() == Type.DOUBLE)
result++;
if (returnType.getSort() != Type.VOID)
result++;
return result;
}
public AbstractValue newValue(Type type) {
if (type == null)
return UnknownValue.UNINITIALIZED_VALUE;
if (type.getSort() == Type.VOID)
return null;
return new UnknownValue(type);
}
/**
* Generates instructions that returns a value.
*
* @param returnType return type of the method this generated bytecode is for
* @param returnValueInsnList instructions that produce the return value (should leave it on the top of the stack)
* @return instructions to return a value
* @throws NullPointerException if any argument is {@code null}
* @throws IllegalArgumentException if {@code returnType}'s sort is of {@link Type#METHOD}
*/
public static InsnList returnValue(Type returnType, InsnList returnValueInsnList) {
Validate.notNull(returnType);
Validate.isTrue(returnType.getSort() != Type.METHOD);
InsnList ret = new InsnList();
ret.add(returnValueInsnList);
switch (returnType.getSort()) {
case Type.VOID:
ret.add(new InsnNode(Opcodes.RETURN));
break;
case Type.BOOLEAN:
case Type.BYTE:
case Type.SHORT:
case Type.CHAR:
case Type.INT:
ret.add(new InsnNode(Opcodes.IRETURN));
break;
case Type.LONG:
ret.add(new InsnNode(Opcodes.LRETURN));
break;
case Type.FLOAT:
ret.add(new InsnNode(Opcodes.FRETURN));
break;
case Type.DOUBLE:
ret.add(new InsnNode(Opcodes.DRETURN));
break;
case Type.OBJECT:
case Type.ARRAY:
ret.add(new InsnNode(Opcodes.ARETURN));
break;
default:
throw new IllegalStateException();
}
return ret;
}
/**
* Compute sizes required for the storage arrays that will contain the operand stack at this frame.
* @param frame frame to compute for
* @param offset the position within the operand stack to start calculating
* @param length the number of stack items to include in calculation
* @return size required by each storage array
* @throws NullPointerException if any argument is {@code null}
* @throws IllegalArgumentException if any numeric argument is negative, or if {@code offset + length} is larger than the size of the
* operand stack
*/
public static StorageSizes computeSizes(Frame<BasicValue> frame, int offset, int length) {
Validate.notNull(frame);
Validate.isTrue(offset >= 0);
Validate.isTrue(length >= 0);
Validate.isTrue(offset < frame.getStackSize());
Validate.isTrue(offset + length <= frame.getStackSize());
// Count size required for each storage array
int intsSize = 0;
int longsSize = 0;
int floatsSize = 0;
int doublesSize = 0;
int objectsSize = 0;
for (int i = offset + length - 1; i >= offset; i--) {
BasicValue basicValue = frame.getStack(i);
Type type = basicValue.getType();
// If type is 'Lnull;', this means that the slot has been assigned null and that "there has been no merge yet that would 'raise'
// the type toward some class or interface type" (from ASM mailing list). We know this slot will always contain null at this
// point in the code so we can avoid saving it. When we load it back up, we can simply push a null in to that slot, thereby
// keeping the same 'Lnull;' type.
if ("Lnull;".equals(type.getDescriptor())) {
continue;
}
switch (type.getSort()) {
case Type.BOOLEAN:
case Type.BYTE:
case Type.SHORT:
case Type.CHAR:
case Type.INT:
intsSize++;
break;
case Type.FLOAT:
floatsSize++;
break;
case Type.LONG:
longsSize++;
break;
case Type.DOUBLE:
doublesSize++;
break;
case Type.ARRAY:
case Type.OBJECT:
objectsSize++;
break;
case Type.METHOD:
case Type.VOID:
default:
throw new IllegalStateException();
}
}
return new StorageSizes(intsSize, longsSize, floatsSize, doublesSize, objectsSize);
}
/**
* Generates a generic "escape" pattern to avoid inserting multiple copies of the same bytecode instructions.
*
* @param methodNode the {@link MethodNode} we are inserting into.
* @return a {@link LabelNode} which "escapes" all other flow.
*/
private static LabelNode exitLabel(MethodNode methodNode) {
LabelNode lb = new LabelNode();
LabelNode escapeNode = new LabelNode();
InsnList insns = methodNode.instructions;
AbstractInsnNode target = insns.getFirst();
insns.insertBefore(target, new JumpInsnNode(GOTO, escapeNode));
insns.insertBefore(target, lb);
switch (Type.getReturnType(methodNode.desc).getSort()) {
case Type.VOID:
insns.insertBefore(target, new InsnNode(RETURN));
break;
case Type.BOOLEAN:
insns.insertBefore(target, ASMUtils.getNumberInsn(RandomUtils.getRandomInt(2)));
insns.insertBefore(target, new InsnNode(IRETURN));
break;
case Type.CHAR:
insns.insertBefore(target, ASMUtils.getNumberInsn(RandomUtils
.getRandomInt(Character.MAX_VALUE + 1)));
insns.insertBefore(target, new InsnNode(IRETURN));
break;
case Type.BYTE:
insns.insertBefore(target, ASMUtils.getNumberInsn(RandomUtils.getRandomInt(Byte.MAX_VALUE + 1)));
insns.insertBefore(target, new InsnNode(IRETURN));
break;
case Type.SHORT:
insns.insertBefore(target, ASMUtils.getNumberInsn(RandomUtils.getRandomInt(Short.MAX_VALUE + 1)));
insns.insertBefore(target, new InsnNode(IRETURN));
break;
case Type.INT:
insns.insertBefore(target, ASMUtils.getNumberInsn(RandomUtils.getRandomInt()));
insns.insertBefore(target, new InsnNode(IRETURN));
break;
case Type.LONG:
insns.insertBefore(target, ASMUtils.getNumberInsn(RandomUtils.getRandomLong()));
insns.insertBefore(target, new InsnNode(LRETURN));
break;
case Type.FLOAT:
insns.insertBefore(target, ASMUtils.getNumberInsn(RandomUtils.getRandomFloat()));
insns.insertBefore(target, new InsnNode(FRETURN));
break;
case Type.DOUBLE:
insns.insertBefore(target, ASMUtils.getNumberInsn(RandomUtils.getRandomDouble()));
insns.insertBefore(target, new InsnNode(DRETURN));
break;
default:
insns.insertBefore(target, new InsnNode(ACONST_NULL));
insns.insertBefore(target, new InsnNode(ARETURN));
break;
}
insns.insertBefore(target, escapeNode);
return lb;
}
private static void generatePushParameterAsObject(final CodeBlock block,
final Type[] paramTypes, int parameterNr)
{
switch (paramTypes[parameterNr++].getSort()) {
case Type.BOOLEAN:
block.iload(parameterNr)
.invokestatic(CodegenUtils.p(Boolean.class), "valueOf",
CodegenUtils.sig(Boolean.class, boolean.class));
return;
case Type.CHAR:
block.iload(parameterNr)
.invokestatic(CodegenUtils.p(Character.class), "valueOf",
CodegenUtils.sig(Character.class, char.class));
return;
case Type.BYTE:
block.iload(parameterNr)
.invokestatic(CodegenUtils.p(Byte.class), "valueOf",
CodegenUtils.sig(Byte.class, byte.class));
return;
case Type.SHORT:
block.iload(parameterNr)
.invokestatic(CodegenUtils.p(Short.class), "valueOf",
CodegenUtils.sig(Short.class, short.class));
return;
case Type.INT:
block.iload(parameterNr)
.invokestatic(CodegenUtils.p(Integer.class), "valueOf",
CodegenUtils.sig(Integer.class, int.class));
return;
case Type.FLOAT:
block.fload(parameterNr)
.invokestatic(CodegenUtils.p(Float.class), "valueOf",
CodegenUtils.sig(Float.class, float.class));
return;
case Type.LONG:
block.lload(parameterNr)
.invokestatic(CodegenUtils.p(Long.class), "valueOf",
CodegenUtils.sig(Long.class, long.class));
return;
case Type.DOUBLE:
block.dload(parameterNr)
.invokestatic(CodegenUtils.p(Double.class), "valueOf",
CodegenUtils.sig(Double.class, double.class));
return;
case Type.ARRAY:
case Type.OBJECT:
block.aload(parameterNr);
return;
case Type.VOID:
default:
throw new IllegalStateException();
}
}
final protected void checkCastReturn(Type returnType) {
final int sort = returnType.getSort();
switch (sort) {
case Type.VOID: {
pop();
mv.visitInsn(Opcodes.RETURN);
break;
}
case Type.BOOLEAN:
case Type.CHAR:
case Type.BYTE:
case Type.SHORT:
case Type.INT: {
unbox(returnType);
returnValue();
break;
}
case Type.FLOAT: {
unbox(returnType);
mv.visitInsn(Opcodes.FRETURN);
break;
}
case Type.LONG: {
unbox(returnType);
mv.visitInsn(Opcodes.LRETURN);
break;
}
case Type.DOUBLE: {
unbox(returnType);
mv.visitInsn(Opcodes.DRETURN);
break;
}
case Type.ARRAY:
case Type.OBJECT:
case Type.METHOD:
default: {
// checkCast(returnType);
unbox(returnType);
mv.visitInsn(ARETURN);
break;
}
}
}
private void weaveOnReturnAdvice(int opcode, Advice advice, Method onReturnAdvice) {
if (onReturnAdvice.getArgumentTypes().length > 0) {
// @BindReturn must be the first argument to @OnReturn (if present)
int startIndex;
Object[] stack;
AdviceParameter parameter = advice.onReturnParameters().get(0);
boolean leaveReturnValueOnStack = onReturnAdvice.getReturnType().getSort() == Type.VOID;
switch (parameter.kind()) {
case RETURN:
loadNonOptionalReturnValue(opcode, parameter, leaveReturnValueOnStack);
startIndex = 1;
if (leaveReturnValueOnStack && opcode != RETURN) {
stack = new Object[] {convert(returnType), convert(parameter.type())};
} else {
stack = new Object[] {convert(parameter.type())};
}
break;
case OPTIONAL_RETURN:
loadOptionalReturnValue(opcode, leaveReturnValueOnStack);
startIndex = 1;
if (leaveReturnValueOnStack && opcode != RETURN) {
stack = new Object[] {convert(returnType), convert(parameter.type())};
} else {
stack = new Object[] {convert(parameter.type())};
}
break;
default:
// first argument is not @BindReturn (which means there is no @BindReturn)
startIndex = 0;
if (opcode == RETURN) {
stack = new Object[] {};
} else {
if (onReturnAdvice.getReturnType().getSort() == Type.VOID) {
stack = new Object[] {convert(returnType)};
} else {
pop();
stack = new Object[] {};
}
}
break;
}
loadMethodParameters(advice.onReturnParameters(), startIndex,
travelerLocals.get(advice), advice.adviceType(), OnReturn.class, true, null,
advice.pointcut().nestingGroup(), advice.pointcut().suppressionKey(), stack);
} else if (onReturnAdvice.getReturnType().getSort() != Type.VOID && opcode != RETURN) {
pop();
}
visitMethodInsn(INVOKESTATIC, advice.adviceType().getInternalName(),
onReturnAdvice.getName(), onReturnAdvice.getDescriptor(), false);
if (onReturnAdvice.getReturnType().getSort() != Type.VOID && opcode == RETURN) {
pop();
}
}
/**
* Generates instructions that returns a dummy value. Return values are as follows:
* <ul>
* <li>void -> no value</li>
* <li>boolean -> false</li>
* <li>byte/short/char/int -> 0</li>
* <li>long -> 0L</li>
* <li>float -> 0.0f</li>
* <li>double -> 0.0</li>
* <li>Object -> null</li>
* </ul>
*
* @param returnType return type of the method this generated bytecode is for
* @return instructions to return a dummy value
* @throws NullPointerException if any argument is {@code null}
* @throws IllegalArgumentException if {@code returnType}'s sort is of {@link Type#METHOD}
*/
private static InsnList returnDummy(Type returnType) {
Validate.notNull(returnType);
Validate.isTrue(returnType.getSort() != Type.METHOD);
InsnList ret = new InsnList();
switch (returnType.getSort()) {
case Type.VOID:
ret.add(new InsnNode(Opcodes.RETURN));
break;
case Type.BOOLEAN:
case Type.BYTE:
case Type.SHORT:
case Type.CHAR:
case Type.INT:
ret.add(new InsnNode(Opcodes.ICONST_0));
ret.add(new InsnNode(Opcodes.IRETURN));
break;
case Type.LONG:
ret.add(new InsnNode(Opcodes.LCONST_0));
ret.add(new InsnNode(Opcodes.LRETURN));
break;
case Type.FLOAT:
ret.add(new InsnNode(Opcodes.FCONST_0));
ret.add(new InsnNode(Opcodes.FRETURN));
break;
case Type.DOUBLE:
ret.add(new InsnNode(Opcodes.DCONST_0));
ret.add(new InsnNode(Opcodes.DRETURN));
break;
case Type.OBJECT:
case Type.ARRAY:
ret.add(new InsnNode(Opcodes.ACONST_NULL));
ret.add(new InsnNode(Opcodes.ARETURN));
break;
default:
throw new IllegalStateException();
}
return ret;
}