下面列出了org.objectweb.asm.Type#getDescriptor ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
@Test
public void parseRegularModel() {
Reporter reporter = new SystemReporter();
ComponentWorkbench workbench = mock(ComponentWorkbench.class);
when(workbench.getType()).thenReturn(Type.getType(MyComponent.class));
when(workbench.getClassNode()).thenReturn(new ClassNode());
when(workbench.getElements()).thenReturn(elements);
FieldNode node = new FieldNode(Opcodes.ACC_PROTECTED, "model", Type.getDescriptor(Crud.class), null, null);
WisdomModelVisitor visitor = new WisdomModelVisitor(workbench, reporter, node);
visitor.visit("value", "entity");
visitor.visitEnd();
assertThat(elements).hasSize(1);
Element element = elements.keySet().iterator().next();
assertThat(element.getName()).isEqualTo("requires");
assertThat(element.getAttribute("field")).isEqualTo("model");
assertThat(element.getAttribute("filter")).contains("=entity)");
}
private Type[] translateTypes(Map<String, String> mapIn, Type... types) {
int index = 0;
Type[] translated = new Type[types.length];
for (Type arg : types) {
switch (arg.getSort()) {
case Type.ARRAY:
// ignore primitive arrays
if (arg.getElementType().getSort() != Type.OBJECT) {
break;
}
case Type.OBJECT:
String desc = arg.getDescriptor();
String heading = desc.substring(0, desc.indexOf('L') + 1);
String name = desc.substring(heading.length(), desc.indexOf(';'));
String newName = mapIn.get(name);
arg = Type.getType(heading + (!Strings.isNullOrEmpty(newName) ? newName : name) + ";");
break;
default:
break;
}
translated[index++] = arg;
}
return translated;
}
static void assembleLocalVariables(final MethodVisitor m, final Label ms, final Label me,
final String invokerDescriptor, final Parameter[] invokeParameters,
final Parameter[] targetMethodParameters, final boolean sendResult) {
final int resultIdx = getResultIdx(invokeParameters);
final int firstVarIdx = getFirstVarIdx(invokeParameters, sendResult);
m.visitLocalVariable("this", invokerDescriptor, null, ms, me, 0);
for (int i = 0; i < invokeParameters.length; i++) {
final Parameter parameter = invokeParameters[i];
final Class<?> parameterType = parameter.getType();
final String descriptor = Type.getDescriptor(parameterType);
//noinspection StringConcatenationMissingWhitespace
m.visitLocalVariable("arg" + i, descriptor, null, ms, me, i + 1);
}
if (sendResult) {
m.visitLocalVariable("result", OBJ_DESCRIPTOR, null, ms, me, resultIdx);
}
for (int i = 0; i < targetMethodParameters.length; i++) {
//noinspection StringConcatenationMissingWhitespace
m.visitLocalVariable("o" + i, OBJ_DESCRIPTOR, null, ms, me, i + firstVarIdx);
}
}
@Test
public void parseModelOnNotCrudField() {
Reporter reporter = new SystemReporter();
ComponentWorkbench workbench = mock(ComponentWorkbench.class);
when(workbench.getType()).thenReturn(Type.getType(MyComponent.class));
when(workbench.getClassNode()).thenReturn(new ClassNode());
when(workbench.getElements()).thenReturn(elements);
FieldNode node = new FieldNode(Opcodes.ACC_PROTECTED, "model", Type.getDescriptor(String.class), null, null);
WisdomModelVisitor visitor = new WisdomModelVisitor(workbench, reporter, node);
visitor.visit("value", "entity");
visitor.visitEnd();
assertThat(elements).hasSize(1);
Element element = elements.keySet().iterator().next();
assertThat(element.getName()).isEqualTo("requires");
assertThat(element.getAttribute("field")).isEqualTo("model");
assertThat(element.getAttribute("filter")).contains("=entity)");
}
private PushInstruction createLdcInstruction(final Object object, final Label label) {
// see MethodVisitor
if (object instanceof Integer) {
return new PushInstruction(object, Types.INTEGER, label);
}
if (object instanceof Float) {
return new PushInstruction(object, Types.FLOAT, label);
}
if (object instanceof Long) {
return new PushInstruction(object, Types.LONG, label);
}
if (object instanceof Double) {
return new PushInstruction(object, Types.DOUBLE, label);
}
if (object instanceof String) {
return new PushInstruction(object, Types.STRING, label);
}
if (object instanceof Type) {
return new PushInstruction(((Type) object).getDescriptor(), Types.CLASS, label);
}
return new PushInstruction(object, Type.getDescriptor(object.getClass()), label);
}
/**
* Constructs a new local variable of the given type.
*
* @param type the type of the local variable to be created.
* @return the identifier of the newly created local variable.
*/
public int newLocal(final Type type) {
Object localType;
switch (type.getSort()) {
case Type.BOOLEAN:
case Type.CHAR:
case Type.BYTE:
case Type.SHORT:
case Type.INT:
localType = Opcodes.INTEGER;
break;
case Type.FLOAT:
localType = Opcodes.FLOAT;
break;
case Type.LONG:
localType = Opcodes.LONG;
break;
case Type.DOUBLE:
localType = Opcodes.DOUBLE;
break;
case Type.ARRAY:
localType = type.getDescriptor();
break;
case Type.OBJECT:
localType = type.getInternalName();
break;
default:
throw new AssertionError();
}
int local = newLocalMapping(type);
setLocalType(local, type);
setFrameLocal(local, localType);
return local;
}
/**
* Converts the supplied object to a descriptor component, used by
* {@link #generateDescriptor}.
*
* @param arg object to convert
*/
private static String toDescriptor(Object arg) {
if (arg instanceof String) {
return (String)arg;
} else if (arg instanceof Type) {
return arg.toString();
} else if (arg instanceof Class) {
return Type.getDescriptor((Class<?>)arg);
}
return arg == null ? "" : arg.toString();
}
public PlayerRendererHookVisitor(String rendererTypeCls, ClassVisitor cv, IResultListener listener) {
super(Opcodes.ASM5, cv);
this.listener = listener;
Type injectedMethodType = Type.getMethodType(Type.VOID_TYPE, MappedType.of(AbstractClientPlayer.class).type(), Type.FLOAT_TYPE, Type.FLOAT_TYPE, Type.FLOAT_TYPE);
modifiedMethod = new MethodMatcher(rendererTypeCls, injectedMethodType.getDescriptor(), "applyRotations", "func_77043_a");
}
/**
* Translates a simple type descriptor, specifically. Only translates names in the
* descriptor, if they are represented by class mirrors.
*
*/
protected String translateDescriptor(final String descriptor) {
Type type = Type.getType(descriptor);
type = getMirrorType(type);
return type.getDescriptor();
}
/**
* Constructs a new local variable of the given type.
*
* @param type the type of the local variable to be created.
* @return the identifier of the newly created local variable.
*/
public int newLocal(final Type type) {
Object localType;
switch (type.getSort()) {
case Type.BOOLEAN:
case Type.CHAR:
case Type.BYTE:
case Type.SHORT:
case Type.INT:
localType = Opcodes.INTEGER;
break;
case Type.FLOAT:
localType = Opcodes.FLOAT;
break;
case Type.LONG:
localType = Opcodes.LONG;
break;
case Type.DOUBLE:
localType = Opcodes.DOUBLE;
break;
case Type.ARRAY:
localType = type.getDescriptor();
break;
case Type.OBJECT:
localType = type.getInternalName();
break;
default:
throw new AssertionError();
}
int local = newLocalMapping(type);
setLocalType(local, type);
setFrameLocal(local, localType);
return local;
}
final <T extends InvokerBase> T buildInvoker(final Class<?> parent, final Method targetMethod, final Method invokerMethod,
final boolean sendResult, final MethodPrefixAssembler prefixAssembler) {
final String packageName = parent.getPackage().getName();
final String invokerClassName = packageName + ".DynamicInvoker$$GeneratedClass$$" + COUNTER.getAndIncrement();
final String invokerInternalName = invokerClassName.replace('.', '/');
final String parentInternalName = Type.getInternalName(parent);
final ClassWriter cw = new ClassWriter(COMPUTE_MAXS);
cw.visit(V1_8, ACC_SUPER | ACC_PUBLIC, invokerInternalName, null, parentInternalName, EMPTY_INTERFACES);
final Type invokerType = Type.getObjectType(invokerInternalName);
final String invokerDescriptor = invokerType.getDescriptor();
assembleConstructor(invokerType, parentInternalName, cw);
assembleMethodHandleField(cw, targetMethod, invokerInternalName);
assembleInvokerMethod(cw, invokerDescriptor, invokerInternalName, invokerMethod, targetMethod, sendResult, prefixAssembler);
cw.visitEnd();
final byte[] bytecode = cw.toByteArray();
final Class<T> cl = CLASS_LOADER.load(bytecode, invokerClassName);
try {
return cl.getDeclaredConstructor().newInstance();
} catch (final IllegalAccessException | InstantiationException | InvocationTargetException | NoSuchMethodException e) {
throw new IllegalStateException(e);
}
}
/**
* @param type
* Array element type.
*
* @return Operand value for a NEWARRAY instruction.
*/
public static int typeToNewArrayArg(Type type) {
switch(type.getDescriptor().charAt(0)) {
case 'Z': return 4;
case 'C': return 5;
case 'F': return 6;
case 'D': return 7;
case 'B': return 8;
case 'S': return 9;
case 'I': return 10;
case 'J': return 11;
default: break;
}
throw new IllegalArgumentException("Unexpected NEWARRAY type: " + type.getDescriptor());
}
private static Type getArrayElementType(Type arrayType) {
int dim = arrayType.getDimensions();
if(dim < 1) throw new IllegalArgumentException("Not an array type: " + arrayType);
if(dim > 1) {
String descr = arrayType.getDescriptor();
return Type.getType(descr.substring(1));
}
return arrayType.getElementType();
}
public PreWorldRenderHookVisitor(String rendererTypeCls, ClassVisitor cv, IResultListener listener) {
super(Opcodes.ASM5, cv);
this.listener = listener;
Type injectedMethodType = Type.getMethodType(Type.VOID_TYPE, Type.INT_TYPE, Type.FLOAT_TYPE, Type.LONG_TYPE);
modifiedMethod = new MethodMatcher(rendererTypeCls, injectedMethodType.getDescriptor(), "renderWorldPass", "func_175068_a");
}
@Override
public void visitLocalVariable(String name, String descriptor, @Nullable String signature,
Label start, Label end, int index) {
// the JSRInlinerAdapter writes the local variable "this" across different label ranges
// so visitedLocalVariableThis is checked and updated to ensure this block is only executed
// once per method
//
if (!name.equals("this") || visitedLocalVariableThis) {
super.visitLocalVariable(name, descriptor, signature, start, end, index);
return;
}
visitedLocalVariableThis = true;
checkNotNull(methodStartLabel, "Call to onMethodEnter() is required");
// this is only so that eclipse debugger will not display <unknown receiving type>
// inside code when inside of code before the previous method start label
// (the debugger asks for "this", which is not otherwise available in the new code
// inserted at the beginning of the method)
//
// ClassReader always visits local variables at the very end (just prior to visitMaxs)
// so this is a good place to put the outer end label for the local variable 'this'
Label outerEndLabel = new Label();
visitLabel(outerEndLabel);
super.visitLocalVariable(name, descriptor, signature, methodStartLabel, outerEndLabel,
index);
// at the same time, may as well define local vars for enabled and traveler as
// applicable
for (int i = 0; i < advisors.size(); i++) {
Advice advice = advisors.get(i);
Integer enabledLocalIndex = enabledLocals.get(advice);
if (enabledLocalIndex != null) {
super.visitLocalVariable("glowroot$enabled$" + i, Type.BOOLEAN_TYPE.getDescriptor(),
null, methodStartLabel, outerEndLabel, enabledLocalIndex);
}
Integer travelerLocalIndex = travelerLocals.get(advice);
if (travelerLocalIndex != null) {
Type travelerType = advice.travelerType();
if (travelerType == null) {
logger.error("visitLocalVariable(): traveler local index is not null,"
+ " but traveler type is null");
} else {
super.visitLocalVariable("glowroot$traveler$" + i, travelerType.getDescriptor(),
null, methodStartLabel, outerEndLabel, travelerLocalIndex);
}
}
}
}
static String key(Class fromClass, Class toClass) {
return Type.getDescriptor(fromClass) + "->" + Type.getDescriptor(toClass);
}
public static MethodInsnNode getWrapperContructionInst(Type type) {
char charType = type.getDescriptor().charAt(0);
String wrapper;
switch (charType) {
case 'B':
wrapper = "java/lang/Byte";
break;
case 'C':
wrapper = "java/lang/Character";
break;
case 'D':
wrapper = "java/lang/Double";
break;
case 'F':
wrapper = "java/lang/Float";
break;
case 'I':
wrapper = "java/lang/Integer";
break;
case 'J':
wrapper = "java/lang/Long";
break;
case 'L':
return null;
case '[':
return null;
case 'Z':
wrapper = "java/lang/Boolean";
break;
case 'S':
wrapper = "java/lang/Short";
break;
default:
throw new ClassFormatError("Invalid method signature: "
+ type.getDescriptor());
}
return new MethodInsnNode(Opcodes.INVOKESTATIC, wrapper, "valueOf",
"(" + charType + ")L" + wrapper + ";", false);
}
final protected void visitFieldInsn(int opcode, Type owner, String name, Type type) {
super.visitFieldInsn(opcode, owner.getInternalName(), name, type.getDescriptor());
}
/**
* Generates an invoke method instruction.
*
* @param opcode the instruction's opcode.
* @param type the class in which the method is defined.
* @param method the method to be invoked.
* @param isInterface whether the 'type' class is an interface or not.
*/
private void invokeInsn(
final int opcode, final Type type, final Method method, final boolean isInterface) {
String owner = type.getSort() == Type.ARRAY ? type.getDescriptor() : type.getInternalName();
mv.visitMethodInsn(opcode, owner, method.getName(), method.getDescriptor(), isInterface);
}
/**
* Generates an invoke method instruction.
*
* @param opcode the instruction's opcode.
* @param type the class in which the method is defined.
* @param method the method to be invoked.
* @param isInterface whether the 'type' class is an interface or not.
*/
private void invokeInsn(
final int opcode, final Type type, final Method method, final boolean isInterface) {
String owner = type.getSort() == Type.ARRAY ? type.getDescriptor() : type.getInternalName();
mv.visitMethodInsn(opcode, owner, method.getName(), method.getDescriptor(), isInterface);
}