下面列出了org.objectweb.asm.Type#getMethodDescriptor ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
public void applyServiceInjectionToSetter(PropertyMetaData property, Method setter) throws Exception {
// GENERATE public void <setter>(<type> value) { <field> == value }
String methodDescriptor = Type.getMethodDescriptor(setter);
Type serviceType = Type.getType(property.getType());
String propFieldName = propFieldName(property);
MethodVisitor methodVisitor = visitor.visitMethod(Opcodes.ACC_PUBLIC, setter.getName(), methodDescriptor, signature(setter), new String[0]);
methodVisitor.visitCode();
// this.field = value
methodVisitor.visitVarInsn(Opcodes.ALOAD, 0);
methodVisitor.visitVarInsn(Opcodes.ALOAD, 1);
methodVisitor.visitFieldInsn(Opcodes.PUTFIELD, generatedType.getInternalName(), propFieldName, serviceType.getDescriptor());
// return
methodVisitor.visitInsn(Opcodes.RETURN);
methodVisitor.visitMaxs(0, 0);
methodVisitor.visitEnd();
}
/**
* This method removes the jumbune mumber from threadLocal signifying that
* jumbune doesn't need to log further information.
*
* @return InsnList list of instructions to be injected
*/
private InsnList stopJumbuneLogging() {
LOGGER.debug("Removing jumbune from ThreadLocal");
InsnList il = new InsnList();
il.add(new LabelNode());
String methodDesc = null;
if (isOldApiClazz()) {
il.add(new VarInsnNode(Opcodes.ALOAD, 0));
il.add(new FieldInsnNode(Opcodes.GETFIELD, ConfigurationUtil
.convertQualifiedClassNameToInternalName(getClassName()),
InstrumentConstants.FIELD_UNLOADLOGGER, "Z"));
methodDesc = Type.getMethodDescriptor(Type.VOID_TYPE,
Type.BOOLEAN_TYPE);
} else {
methodDesc = EMPTY_PARAMETER_VOID_RETURN;
}
il.add(new MethodInsnNode(Opcodes.INVOKESTATIC,
CLASSNAME_MAPREDUCEEXECUTIL, "stopJumbuneLogging", methodDesc));
return il;
}
/**
* <p>
* This method provides instruction to log method entry/exit information
* </p>
*
* @param className
* Class which has called the logger
* @param methodName
* Method in which the logger has been called
* @param logMsg
* log message
* @return InsnList Instructions
*/
public static InsnList addLogMessage(Object... objects) {
String method = "addLogMsg";
InsnList il = getBasicInstructions(objects);
Type[] types = new Type[objects.length];
for (int i = 0; i < objects.length; i++) {
types[i] = TYPE_OBJECT;
}
String methodDesc = Type.getMethodDescriptor(Type.VOID_TYPE, types);
il.add(new MethodInsnNode(Opcodes.INVOKESTATIC, CLASSNAME_LOGUTIL,
method, methodDesc));
return il;
}
private static String createDescriptor(TypeWidget returnType, List<TypeWidget> argsWidgets) {
Type rt = returnType.getJVMType();
List<Type> argTypes = Lists.newArrayListWithExpectedSize(argsWidgets.size());
for (TypeWidget argsWidget : argsWidgets) {
argTypes.add(argsWidget.getJVMType());
}
return Type.getMethodDescriptor(rt, argTypes.toArray(new Type[argTypes.size()]));
}
public static AbstractInsnNode tableRawSetIntKey() {
return new MethodInsnNode(
INVOKEVIRTUAL,
Type.getInternalName(Table.class),
"rawset",
Type.getMethodDescriptor(
Type.VOID_TYPE,
Type.INT_TYPE,
Type.getType(Object.class)),
false);
}
/**
* This method adds statement for calling LogUtil method so it can log
* information about partitioner It will construct below statement:
*
* LogUtil.getPartitionerInfo(className, methodName, logLevel, message,
* sampleCount, timeTaken );
*
* @param logBean
* - bean containing information to log
* @return InstructionList for calling LogUtil.getPartitionerInfo method
*/
public static InsnList addLoggingForPartitioner(LogInfoBean logBean) {
String logMethodDesc = Type.getMethodDescriptor(Type.VOID_TYPE,
TYPE_STRING, TYPE_STRING, TYPE_STRING,
Type.getType(Long.class), Type.getType(Long.class));
InsnList il = new InsnList();
il.add(createBasicLoggerInsns(logBean));
LOGGER.debug("logMethodDes " + logMethodDesc
+ " METHOD_DESC_RETURN_LONG "
+ InstrumentConstants.METHOD_DESC_RETURN_LONG);
il.add(new MethodInsnNode(Opcodes.INVOKESTATIC,
InstrumentConstants.CLASSNAME_MAPREDUCEEXECUTIL,
InstrumentConstants.GET_PARTITIONING_SAMPLE_COUNT,
InstrumentConstants.METHOD_DESC_RETURN_LONG));
il.add(new MethodInsnNode(Opcodes.INVOKESTATIC,
InstrumentConstants.CLASSNAME_MAPREDUCEEXECUTIL,
InstrumentConstants.GET_PARTITIONING_TIME_TAKEN,
InstrumentConstants.METHOD_DESC_RETURN_LONG));
il.add(new MethodInsnNode(Opcodes.INVOKESTATIC, CLASSNAME_LOGUTIL,
InstrumentConstants.PARTITIONER_INFO, logMethodDesc));
return il;
}
String getDesc() {
List<String> parameterTypes = parameterTypes();
Type[] types = new Type[parameterTypes.size()];
for (int i = 0; i < parameterTypes.size(); i++) {
types[i] = getType(parameterTypes.get(i));
}
return Type.getMethodDescriptor(getType(returnType()), types);
}
@Test
public void mustCreateAndRunIfIntStatements() throws Exception {
// Augment signature
methodNode.desc = Type.getMethodDescriptor(Type.getType(String.class), new Type[] { Type.INT_TYPE, Type.INT_TYPE });
// Initialize variable table
VariableTable varTable = new VariableTable(classNode, methodNode);
Variable intVar1 = varTable.getArgument(1);
Variable intVar2 = varTable.getArgument(2);
// Update method logic
/**
* if (arg1 == arg2) {
* return "match";
* }
* return "nomatch";
*/
methodNode.instructions
= merge(ifIntegersEqual(loadVar(intVar1),
loadVar(intVar2),
returnValue(Type.getType(String.class), loadStringConst("match"))),
returnValue(Type.getType(String.class), loadStringConst("nomatch"))
);
// Write to JAR file + load up in classloader -- then execute tests
try (URLClassLoader cl = createJarAndLoad(classNode)) {
Object obj = cl.loadClass(STUB_CLASSNAME).newInstance();
assertEquals("match", MethodUtils.invokeMethod(obj, STUB_METHOD_NAME, 2, 2));
assertEquals("nomatch", MethodUtils.invokeMethod(obj, STUB_METHOD_NAME, -2, 2));
assertEquals("match", MethodUtils.invokeMethod(obj, STUB_METHOD_NAME, -2, -2));
}
}
public static AbstractInsnNode floatValueOf() {
return new MethodInsnNode(
INVOKESTATIC,
Type.getInternalName(Conversions.class),
"floatValueOf",
Type.getMethodDescriptor(
Type.getType(Double.class),
Type.getType(Object.class)),
false);
}
public String createMethodDescriptor() {
List<TypeWidget> argumentTypes = getArgumentTypes();
Type[] argTypes = new Type[argumentTypes.size()];
int i = 0;
for (TypeWidget t : argumentTypes) {
argTypes[i++] = t.getJVMType();
}
return Type.getMethodDescriptor(getReturnJVMType(), argTypes);
}
public static AbstractInsnNode set() {
return new MethodInsnNode(
INVOKEVIRTUAL,
Type.getInternalName(Variable.class),
"set",
Type.getMethodDescriptor(
Type.VOID_TYPE,
Type.getType(Object.class)),
false);
}
private static String methodDescriptor(Class<?> returnType, Class<?>... parameterTypes) {
Type[] argumentTypes = new Type[parameterTypes.length];
int typeIndex = 0;
for (Class<?> parameterType : parameterTypes) {
argumentTypes[typeIndex++] = Type.getType(parameterType);
}
return Type.getMethodDescriptor(Type.getType(returnType), argumentTypes);
}
public void invokeSpecial(String name, Type ownerType, Type returnType, Type... parameterTypes) {
super.visitMethodInsn(
INVOKESPECIAL,
ownerType.getInternalName(),
name,
Type.getMethodDescriptor(returnType, parameterTypes),
false
);
}
@SuppressWarnings("unchecked")
protected void writeDestructor() {
if (entity.methodDestruct != null) {
MethodNode destructor = new MethodNodeImpl();
destructor.name = "finalize";
destructor.access = ACC_PUBLIC;
destructor.desc = Type.getMethodDescriptor(Type.getType(void.class));
MethodStmtCompiler methodCompiler = new MethodStmtCompiler(this, destructor);
ExpressionStmtCompiler expressionCompiler = new ExpressionStmtCompiler(methodCompiler, null);
methodCompiler.writeHeader();
LabelNode end = new LabelNode();
LabelNode l0 = writeLabel(destructor, statement.getMeta().getStartLine());
methodCompiler.addLocalVariable(LocalVariable.THIS, l0);
expressionCompiler.writeVarLoad(LocalVariable.THIS);
expressionCompiler.writeSysDynamicCall(null, "isFinalized", Boolean.TYPE);
destructor.instructions.add(new JumpInsnNode(IFEQ, end));
// --- if (!__finalized__) {
expressionCompiler.writeVarLoad(LocalVariable.THIS);
expressionCompiler.writePushDup();
expressionCompiler.writeSysDynamicCall(null, "doFinalize", void.class);
expressionCompiler.writePushEnvFromSelf();
expressionCompiler.writePushConstNull();
expressionCompiler.writeSysDynamicCall(
null, entity.methodDestruct.getInternalName(), Memory.class, Environment.class, Memory[].class
);
expressionCompiler.writePopAll(1);
// ---- }
destructor.instructions.add(end);
// call parent
// WARNING!!! It's commented for better performance, super.finalize empty in JDK 1.6, 1.7, 1.8
/*expressionCompiler.writeVarLoad("~this");
destructor.instructions.add(new MethodInsnNode(
INVOKEVIRTUAL,
Type.getInternalName(Object.class),
destructor.name,
destructor.desc
));*/
destructor.instructions.add(new InsnNode(Opcodes.RETURN));
methodCompiler.writeFooter();
node.methods.add(destructor);
}
}
private void addGetter(Method method, MethodCodeBody body) throws Exception {
String methodDescriptor = Type.getMethodDescriptor(method);
String methodName = method.getName();
addGetter(methodName, methodDescriptor, body);
}
public void applyServiceInjectionToGetter(PropertyMetaData property, Method getter) throws Exception {
// GENERATE public <type> <getter>() { if (<field> == null) { <field> = getServices().get(getClass().getDeclaredMethod(<getter-name>).getGenericReturnType()); } return <field> }
Type serviceRegistryType = Type.getType(ServiceRegistry.class);
Type classType = Type.getType(Class.class);
Type methodType = Type.getType(Method.class);
Type typeType = Type.getType(java.lang.reflect.Type.class);
String getterName = getter.getName();
Type returnType = Type.getType(getter.getReturnType());
String methodDescriptor = Type.getMethodDescriptor(returnType);
Type serviceType = Type.getType(property.getType());
String propFieldName = propFieldName(property);
MethodVisitor methodVisitor = visitor.visitMethod(Opcodes.ACC_PUBLIC, getterName, methodDescriptor, signature(getter), new String[0]);
methodVisitor.visitCode();
// if (this.<field> == null) { ... }
// this.field
methodVisitor.visitVarInsn(Opcodes.ALOAD, 0);
methodVisitor.visitFieldInsn(Opcodes.GETFIELD, generatedType.getInternalName(), propFieldName, serviceType.getDescriptor());
Label alreadyLoaded = new Label();
methodVisitor.visitJumpInsn(Opcodes.IFNONNULL, alreadyLoaded);
methodVisitor.visitVarInsn(Opcodes.ALOAD, 0);
// this.getServices()
methodVisitor.visitVarInsn(Opcodes.ALOAD, 0);
methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, generatedType.getInternalName(), "getServices", Type.getMethodDescriptor(serviceRegistryType));
// this.getClass()
methodVisitor.visitVarInsn(Opcodes.ALOAD, 0);
methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, generatedType.getInternalName(), "getClass", Type.getMethodDescriptor(classType));
// <class>.getDeclaredMethod(<getter-name>)
methodVisitor.visitLdcInsn(getterName);
methodVisitor.visitInsn(Opcodes.ICONST_0);
methodVisitor.visitTypeInsn(Opcodes.ANEWARRAY, classType.getInternalName());
methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, classType.getInternalName(), "getDeclaredMethod", Type.getMethodDescriptor(methodType, Type.getType(String.class), Type.getType(Class[].class)));
// <method>.getGenericReturnType()
methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, methodType.getInternalName(), "getGenericReturnType", Type.getMethodDescriptor(typeType));
// get(<type>)
methodVisitor.visitMethodInsn(Opcodes.INVOKEINTERFACE, serviceRegistryType.getInternalName(), "get", Type.getMethodDescriptor(Type.getType(Object.class), typeType));
// this.field = (<type>)<service>
methodVisitor.visitTypeInsn(Opcodes.CHECKCAST, serviceType.getInternalName());
methodVisitor.visitFieldInsn(Opcodes.PUTFIELD, generatedType.getInternalName(), propFieldName, serviceType.getDescriptor());
// this.field
methodVisitor.visitLabel(alreadyLoaded);
methodVisitor.visitVarInsn(Opcodes.ALOAD, 0);
methodVisitor.visitFieldInsn(Opcodes.GETFIELD, generatedType.getInternalName(), propFieldName, serviceType.getDescriptor());
// return
methodVisitor.visitInsn(returnType.getOpcode(Opcodes.IRETURN));
methodVisitor.visitMaxs(0, 0);
methodVisitor.visitEnd();
}
public static void assembleInvokerMethod(final ClassWriter cw, final String invokerDescriptor, final String invokerInternalName,
final Method invokerMethod, final Method targetMethod, final boolean sendResult,
final MethodPrefixAssembler prefixAssembler) {
final String methodDescriptor = Type.getMethodDescriptor(invokerMethod);
final String methodName = invokerMethod.getName();
final MethodVisitor m = cw.visitMethod(ACC_PUBLIC, methodName, methodDescriptor, null, null);
final Label ms = createLabel();
final Label me = createLabel();
m.visitCode();
m.visitLabel(ms);
final Parameter[] invokeParameters = invokerMethod.getParameters();
final int resultIdx = getResultIdx(invokeParameters);
final int firstVarIdx = getFirstVarIdx(invokeParameters, sendResult);
prefixAssembler.assemble(invokerInternalName, m, firstVarIdx);
m.visitFieldInsn(GETSTATIC, invokerInternalName, "HANDLE", MH_DESCRIPTOR);
m.visitIntInsn(ALOAD, 0);
m.visitFieldInsn(GETFIELD, invokerInternalName, "bean", OBJ_DESCRIPTOR);
final Parameter[] targetMethodParameters = targetMethod.getParameters();
for (int i = 0; i < targetMethodParameters.length; i++) {
m.visitIntInsn(ALOAD, i + firstVarIdx);
}
final String[] paramDescriptors = new String[targetMethodParameters.length + 1];
Arrays.fill(paramDescriptors, OBJ_DESCRIPTOR);
final String tmd = '(' + String.join("", paramDescriptors) + ')' + OBJ_DESCRIPTOR;
m.visitMethodInsn(INVOKEVIRTUAL, MH_INTERNAL_NAME, "invokeExact", tmd, false);
if (sendResult) {
final int channelArgIdx = IntStream.range(0, invokeParameters.length)
.filter(i -> {
final Parameter parameter = invokeParameters[i];
final Class<?> type = parameter.getType();
return Channel.class.isAssignableFrom(type);
})
.findFirst()
.orElse(-2) + 1;
m.visitIntInsn(ASTORE, resultIdx);
m.visitIntInsn(ALOAD, channelArgIdx);
m.visitIntInsn(ALOAD, resultIdx);
m.visitMethodInsn(INVOKEINTERFACE, CHANNEL_INTERNAL_NAME, "writeAndFlush",
CHANNEL_WRITE_AND_FLUSH_DESCRIPTOR, true);
}
m.visitInsn(POP);
m.visitInsn(RETURN);
m.visitLabel(me);
assembleLocalVariables(m, ms, me, invokerDescriptor, invokeParameters, targetMethodParameters, sendResult);
m.visitEnd();
m.visitMaxs(0, 0);
}
public void addActionMethod(Method method) throws Exception {
Type actionImplType = Type.getType(ClosureBackedAction.class);
Type closureType = Type.getType(Closure.class);
Type returnType = Type.getType(method.getReturnType());
Type[] originalParameterTypes = CollectionUtils.collectArray(method.getParameterTypes(), Type.class, new Transformer<Type, Class>() {
public Type transform(Class clazz) {
return Type.getType(clazz);
}
});
int numParams = originalParameterTypes.length;
Type[] closurisedParameterTypes = new Type[numParams];
System.arraycopy(originalParameterTypes, 0, closurisedParameterTypes, 0, numParams);
closurisedParameterTypes[numParams - 1] = closureType;
String methodDescriptor = Type.getMethodDescriptor(returnType, closurisedParameterTypes);
// GENERATE public <return type> <method>(Closure v) { return <method>(…, new ClosureBackedAction(v)); }
MethodVisitor methodVisitor = visitor.visitMethod(Opcodes.ACC_PUBLIC, method.getName(), methodDescriptor, null, new String[0]);
methodVisitor.visitCode();
// GENERATE <method>(…, new ClosureBackedAction(v));
methodVisitor.visitVarInsn(Opcodes.ALOAD, 0);
for (int stackVar = 1; stackVar < numParams; ++stackVar) {
methodVisitor.visitVarInsn(closurisedParameterTypes[stackVar - 1].getOpcode(Opcodes.ILOAD), stackVar);
}
// GENERATE new ClosureBackedAction(v);
methodVisitor.visitTypeInsn(Opcodes.NEW, actionImplType.getInternalName());
methodVisitor.visitInsn(Opcodes.DUP);
methodVisitor.visitVarInsn(Opcodes.ALOAD, numParams);
String constuctorDescriptor = Type.getMethodDescriptor(Type.VOID_TYPE, closureType);
methodVisitor.visitMethodInsn(Opcodes.INVOKESPECIAL, actionImplType.getInternalName(), "<init>", constuctorDescriptor);
methodDescriptor = Type.getMethodDescriptor(Type.getType(method.getReturnType()), originalParameterTypes);
methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, generatedType.getInternalName(), method.getName(), methodDescriptor);
methodVisitor.visitInsn(returnType.getOpcode(Opcodes.IRETURN));
methodVisitor.visitMaxs(0, 0);
methodVisitor.visitEnd();
}
@Test
public void mustCreateAndRunForEachStatement() throws Exception {
// Augment signature
methodNode.desc = Type.getMethodDescriptor(Type.getType(String.class), new Type[] {
Type.getType(Object[].class),
Type.getType(Object.class)
});
methodNode.maxLocals += 2; // We've added 2 parameters to the method, and we need to upgrade maxLocals or else varTable will give
// us bad indexes for variables we grab with acquireExtra(). This is because VariableTable uses maxLocals
// to determine at what point to start adding extra local variables.
// Initialize variable table
VariableTable varTable = new VariableTable(classNode, methodNode);
Variable objectArrVar = varTable.getArgument(1);
Variable searchObjVar = varTable.getArgument(2);
Variable counterVar = varTable.acquireExtra(Type.INT_TYPE);
Variable arrayLenVar = varTable.acquireExtra(Type.INT_TYPE);
Variable tempObjectVar = varTable.acquireExtra(Object.class);
// Update method logic
/**
* for (Object[] o : arg1) {
* if (o == arg2) {
* return "match";
* }
* }
* return "nomatch";
*/
methodNode.instructions
= merge(
forEach(counterVar, arrayLenVar,
loadVar(objectArrVar),
merge(
saveVar(tempObjectVar),
ifObjectsEqual(loadVar(tempObjectVar), loadVar(searchObjVar),
returnValue(Type.getType(String.class), loadStringConst("match")))
)
),
returnValue(Type.getType(String.class), loadStringConst("nomatch"))
);
// Write to JAR file + load up in classloader -- then execute tests
try (URLClassLoader cl = createJarAndLoad(classNode)) {
Object obj = cl.loadClass(STUB_CLASSNAME).newInstance();
Object o1 = new Object();
Object o2 = new Object();
Object o3 = new Object();
assertEquals("match", MethodUtils.invokeMethod(obj, STUB_METHOD_NAME, (Object) new Object[] { o1, o2, o3 }, o1));
assertEquals("match", MethodUtils.invokeMethod(obj, STUB_METHOD_NAME, (Object) new Object[] { o1, o2, o3 }, o2));
assertEquals("match", MethodUtils.invokeMethod(obj, STUB_METHOD_NAME, (Object) new Object[] { o1, o2, o3 }, o3));
assertEquals("nomatch", MethodUtils.invokeMethod(obj, STUB_METHOD_NAME, (Object) new Object[] { o1, o2, o3 }, null));
assertEquals("nomatch", MethodUtils.invokeMethod(obj, STUB_METHOD_NAME, (Object) new Object[] { o1, o2, o3 }, new Object()));
}
}
/**
* Creates a new {@link Method}.
*
* @param method a java.lang.reflect method descriptor
* @return a {@link Method} corresponding to the given Java method declaration.
*/
public static Method getMethod(final java.lang.reflect.Method method) {
return new Method(method.getName(), Type.getMethodDescriptor(method));
}