下面列出了org.objectweb.asm.commons.Method#getMethod ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
@Override
public void visitCode(){
super.visitCode();
// Push the current stack size to operand stack and invoke AVMStackWatcher.enterMethod(int)
Method m1 = Method.getMethod("void enterMethod(int)");
visitLdcInsn(this.maxLocals + this.maxStack);
invokeStatic(typeHelper, m1);
// If current method has at least one try catch block, we need to generate a StackWacher stamp.
if (this.tryCatchBlockCount > 0){
//invoke AVMStackWatcher.getCurStackDepth() and put the result into local variable
Method m2 = Method.getMethod("int getCurStackDepth()");
invokeStatic(typeHelper, m2);
this.stackDepthLocalVariableIndex = newLocal(typeInt);
storeLocal(this.stackDepthLocalVariableIndex, typeInt);
//invoke AVMStackWatcher.getCurStackSize() and put the result into local variable
Method m3 = Method.getMethod("int getCurStackSize()");
invokeStatic(typeHelper, m3);
this.stackSizeLocalVariableIndex = newLocal(typeInt);
storeLocal(this.stackSizeLocalVariableIndex, typeInt);
}
}
@RequiresNonNull("type")
private void addShim(ShimType shimType) {
for (java.lang.reflect.Method reflectMethod : shimType.shimMethods()) {
Method method = Method.getMethod(reflectMethod);
Shim shim = reflectMethod.getAnnotation(Shim.class);
checkNotNull(shim);
if (shim.value().length != 1) {
throw new IllegalStateException(
"@Shim annotation must have exactly one value when used on methods");
}
Method targetMethod = Method.getMethod(shim.value()[0]);
MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, method.getName(), method.getDescriptor(),
null, null);
mv.visitCode();
int i = 0;
mv.visitVarInsn(ALOAD, i++);
for (Type argumentType : method.getArgumentTypes()) {
mv.visitVarInsn(argumentType.getOpcode(ILOAD), i++);
}
mv.visitMethodInsn(INVOKEVIRTUAL, type.getInternalName(), targetMethod.getName(),
targetMethod.getDescriptor(), false);
mv.visitInsn(method.getReturnType().getOpcode(IRETURN));
mv.visitMaxs(0, 0);
mv.visitEnd();
}
}
private static void defineSuperAccessorMethod(ClassWriter cw, java.lang.reflect.Method method, Type superType,
String superAccessorMethodSuffix)
{
Method originalAsmMethod = Method.getMethod(method);
Method newAsmMethod = new Method(method.getName() + superAccessorMethodSuffix,
originalAsmMethod.getReturnType(),
originalAsmMethod.getArgumentTypes());
GeneratorAdapter mg = new GeneratorAdapter(Opcodes.ACC_PUBLIC, newAsmMethod, null, null, cw);
mg.visitCode();
// call super method
mg.loadThis();
mg.loadArgs();
mg.visitMethodInsn(Opcodes.INVOKESPECIAL,
superType.getInternalName(),
method.getName(),
Type.getMethodDescriptor(method),
false);
mg.returnValue();
// finish the method
mg.endMethod();
mg.visitMaxs(10, 10);
mg.visitEnd();
}
@Override
protected void onMethodExit(int opcode){
// Push the current stack size to operand stack and invoke AVMStackWatcher.exitMethod(int)
Method m1 = Method.getMethod("void exitMethod(int)");
visitLdcInsn(this.maxLocals + this.maxStack);
invokeStatic(typeHelper, m1);
}
@Override
public void visitLabel(Label label){
mv.visitLabel(label);
// We instrument the code (start of catch block) if the label we are visiting is an exception handler
if (catchBlockList.contains(label)){
// Load the stamp from LVT
loadLocal(this.stackDepthLocalVariableIndex, typeInt);
loadLocal(this.stackSizeLocalVariableIndex, typeInt);
Method m1 = Method.getMethod("void enterCatchBlock(int, int)");
invokeStatic(typeHelper, m1);
}
}
public WeavingClassVisitor(ClassWriter cw, @Nullable ClassLoader loader, boolean frames,
boolean noLongerNeedToWeaveMainMethods, AnalyzedClass analyzedClass,
boolean isClassLoader, List<AnalyzedMethod> methodsThatOnlyNowFulfillAdvice,
List<ShimType> shimTypes, List<MixinType> mixinTypes,
Map<String, List<Advice>> methodAdvisors, AnalyzedWorld analyzedWorld) {
super(ASM7, cw);
this.cw = cw;
this.loader = loader;
this.frames = frames;
this.noLongerNeedToWeaveMainMethods = noLongerNeedToWeaveMainMethods;
this.isClassLoader = isClassLoader;
this.analyzedClass = analyzedClass;
this.methodsThatOnlyNowFulfillAdvice = methodsThatOnlyNowFulfillAdvice;
this.shimTypes = shimTypes;
this.mixinTypes = mixinTypes;
this.methodAdvisors = methodAdvisors;
this.analyzedWorld = analyzedWorld;
shimMethods = Sets.newHashSet();
for (ShimType shimType : shimTypes) {
for (java.lang.reflect.Method shimMethod : shimType.shimMethods()) {
Method method = Method.getMethod(shimMethod);
shimMethods.add(method.getName() + method.getDescriptor());
}
}
// cannot store ClassNode in MixinType and re-use across MethodClassVisitors because
// MethodNode.accept() cannot be called multiple times (at least not across multiple
// threads) without throwing an occassional NPE
mixinClassNodes = Lists.newArrayList();
if (!analyzedClass.isInterface()) {
for (MixinType mixinType : mixinTypes) {
ClassReader cr = new ClassReader(mixinType.implementationBytes());
ClassNode cn = new ClassNode();
cr.accept(cn, ClassReader.EXPAND_FRAMES);
mixinClassNodes.add(cn);
}
}
}
public InjectorMethodVisitor(MethodVisitor mv) {
super(Opcodes.ASM5, mv);
try {
postMethod = Method.getMethod(PlayerRendererHookVisitor.class.getMethod("post", AbstractClientPlayer.class, float.class));
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
}
Log.debug("Injecting hook %s.%s into EntityPlayerRender.rotateCorpse", PlayerRendererHookVisitor.class, postMethod);
}
public InjectorMethodVisitor(MethodVisitor mv) {
super(Opcodes.ASM5, mv);
try {
hookCls = Type.getType(PreWorldRenderHookVisitor.class);
hookMethod = Method.getMethod(PreWorldRenderHookVisitor.class.getMethod("callHook"));
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
}
Log.debug("Injecting hook %s.%s into EntityRenderer.renderWorldPass", PreWorldRenderHookVisitor.class, hookMethod);
}
@Override
public void visitInsn(final int opcode) {
Method m;
switch (opcode) {
// Static type
case Opcodes.CALOAD:
m = Method.getMethod("char get(int)");
invokeVirtual(typeCA, m);
break;
case Opcodes.DALOAD:
m = Method.getMethod("double get(int)");
invokeVirtual(typeDA, m);
break;
case Opcodes.FALOAD:
m = Method.getMethod("float get(int)");
invokeVirtual(typeFA, m);
break;
case Opcodes.IALOAD:
m = Method.getMethod("int get(int)");
invokeVirtual(typeIA, m);
break;
case Opcodes.LALOAD:
m = Method.getMethod("long get(int)");
invokeVirtual(typeLA, m);
break;
case Opcodes.SALOAD:
m = Method.getMethod("short get(int)");
invokeVirtual(typeSA, m);
break;
case Opcodes.CASTORE:
m = Method.getMethod("void set(int, char)");
invokeVirtual(typeCA, m);
break;
case Opcodes.DASTORE:
m = Method.getMethod("void set(int, double)");
invokeVirtual(typeDA, m);
break;
case Opcodes.FASTORE:
m = Method.getMethod("void set(int, float)");
invokeVirtual(typeFA, m);
break;
case Opcodes.IASTORE:
m = Method.getMethod("void set(int, int)");
invokeVirtual(typeIA, m);
break;
case Opcodes.LASTORE:
m = Method.getMethod("void set(int, long)");
invokeVirtual(typeLA, m);
break;
case Opcodes.SASTORE:
m = Method.getMethod("void set(int, short)");
invokeVirtual(typeSA, m);
break;
case Opcodes.ARRAYLENGTH:
m = Method.getMethod("int length()");
invokeInterface(typeA, m);
break;
case Opcodes.AALOAD:
throw RuntimeAssertionError.unreachable("Primitive array wrapping adapter catch AALOAD");
case Opcodes.AASTORE:
throw RuntimeAssertionError.unreachable("Primitive array wrapping adapter catch AASTORE");
default:
this.mv.visitInsn(opcode);
}
}
@Override
public void visitIntInsn(final int opcode, final int operand) {
Method m;
if (opcode == Opcodes.NEWARRAY) {
switch (operand) {
case Opcodes.T_BOOLEAN:
m = Method.getMethod(PackageConstants.kArrayWrapperDotPrefix + "BooleanArray initArray(int)");
invokeStatic(typeZA, m);
break;
case Opcodes.T_BYTE:
m = Method.getMethod(PackageConstants.kArrayWrapperDotPrefix + "ByteArray initArray(int)");
invokeStatic(typeBA, m);
break;
case Opcodes.T_SHORT:
m = Method.getMethod(PackageConstants.kArrayWrapperDotPrefix + "ShortArray initArray(int)");
invokeStatic(typeSA, m);
break;
case Opcodes.T_INT:
m = Method.getMethod(PackageConstants.kArrayWrapperDotPrefix + "IntArray initArray(int)");
invokeStatic(typeIA, m);
break;
case Opcodes.T_LONG:
m = Method.getMethod(PackageConstants.kArrayWrapperDotPrefix + "LongArray initArray(int)");
invokeStatic(typeLA, m);
break;
case Opcodes.T_CHAR:
m = Method.getMethod(PackageConstants.kArrayWrapperDotPrefix + "CharArray initArray(int)");
invokeStatic(typeCA, m);
break;
case Opcodes.T_FLOAT:
m = Method.getMethod(PackageConstants.kArrayWrapperDotPrefix + "FloatArray initArray(int)");
invokeStatic(typeFA, m);
break;
case Opcodes.T_DOUBLE:
m = Method.getMethod(PackageConstants.kArrayWrapperDotPrefix + "DoubleArray initArray(int)");
invokeStatic(typeDA, m);
break;
default:
this.mv.visitIntInsn(opcode, operand);
}
}else{
this.mv.visitIntInsn(opcode, operand);
}
}
static Method getAsmMethod(final Class<?> clazz,
final String methodName,
final Class<?>... parameterClassArray) {
return Method.getMethod(unCaughtGetClassDeclaredJavaMethod(clazz, methodName, parameterClassArray));
}
private static void generateRun(ClassVisitor cv, Type testType, int iThread, List<Actor> actors, List<Object> objArgs, boolean waitsEnabled) {
int access = ACC_PUBLIC;
Method m = new Method("call", RESULT_ARRAY_TYPE, NO_ARGS);
GeneratorAdapter mv = new GeneratorAdapter(access, m,
// Try-catch blocks sorting is required
new TryCatchBlockSorter(cv.visitMethod(access, m.getName(), m.getDescriptor(), null, null),
access, m.getName(), m.getDescriptor(), null, null)
);
mv.visitCode();
// Create Result[] array and store it to a local variable
int resLocal = createResultArray(mv, actors.size());
// Call runner's onStart(iThread) method
mv.loadThis();
mv.getField(TEST_THREAD_EXECUTION_TYPE, "runner", RUNNER_TYPE);
mv.push(iThread);
mv.invokeVirtual(RUNNER_TYPE, RUNNER_ON_START_METHOD);
// Number of current operation (starts with 0)
int iLocal = mv.newLocal(Type.INT_TYPE);
mv.push(0);
mv.storeLocal(iLocal);
// Invoke actors
for (int i = 0; i < actors.size(); i++) {
Actor actor = actors.get(i);
// Add busy-wait before operation execution (for non-first operations only)
if (waitsEnabled && i > 0) {
mv.loadThis();
mv.getField(TEST_THREAD_EXECUTION_TYPE, "waits", INT_ARRAY_TYPE);
mv.push(i - 1);
mv.arrayLoad(Type.INT_TYPE);
mv.invokeStatic(UTILS_TYPE, UTILS_CONSUME_CPU);
}
// Start of try-catch block for exceptions which this actor should handle
Label start, end = null, handler = null, handlerEnd = null;
if (actor.handlesExceptions()) {
start = mv.newLabel();
end = mv.newLabel();
handler = mv.newLabel();
handlerEnd = mv.newLabel();
for (Class<? extends Throwable> ec : actor.handledExceptions)
mv.visitTryCatchBlock(start, end, handler, Type.getType(ec).getInternalName());
mv.visitLabel(start);
}
// Load result array and index to store the current result
mv.loadLocal(resLocal);
mv.push(i);
// Load test instance
mv.loadThis();
mv.getField(TEST_THREAD_EXECUTION_TYPE, "testInstance", OBJECT_TYPE);
mv.checkCast(testType);
// Load arguments for operation
for (int j = 0; j < actor.arguments.length; j++) {
pushArgumentOnStack(mv, objArgs, actor.arguments[j], actor.method.getParameterTypes()[j]);
}
// Invoke operation
Method actorMethod = Method.getMethod(actor.method);
mv.invokeVirtual(testType, actorMethod);
// Create result
mv.box(actorMethod.getReturnType()); // box if needed
if (actor.method.getReturnType() == void.class) {
mv.pop();
mv.invokeStatic(RESULT_TYPE, RESULT_CREATE_VOID_RESULT);
} else {
mv.invokeStatic(RESULT_TYPE, RESULT_CREATE_VALUE_RESULT);
}
// Store result to array
mv.arrayStore(RESULT_TYPE);
// End of try-catch block
if (actor.handlesExceptions()) {
mv.visitLabel(end);
mv.goTo(handlerEnd);
mv.visitLabel(handler);
storeExceptionResultFromThrowable(mv, resLocal, iLocal);
mv.visitLabel(handlerEnd);
}
// Increment number of current operation
mv.iinc(iLocal, 1);
}
// Call runner's onFinish(iThread) method
mv.loadThis();
mv.getField(TEST_THREAD_EXECUTION_TYPE, "runner", RUNNER_TYPE);
mv.push(iThread);
mv.invokeVirtual(RUNNER_TYPE, RUNNER_ON_FINISH_METHOD);
// Return results
mv.loadThis();
mv.loadLocal(resLocal);
mv.returnValue();
mv.visitMaxs(1, 1);
mv.visitEnd();
}
private static void defineMethod(ClassWriter cw, java.lang.reflect.Method method, Type proxyType)
{
Type methodType = Type.getType(method);
ArrayList<Type> exceptionsToCatch = new ArrayList<Type>();
for (Class<?> exception : method.getExceptionTypes())
{
if (!RuntimeException.class.isAssignableFrom(exception))
{
exceptionsToCatch.add(Type.getType(exception));
}
}
// push the method definition
int modifiers = (Opcodes.ACC_PUBLIC | Opcodes.ACC_PROTECTED) & method.getModifiers();
Method asmMethod = Method.getMethod(method);
GeneratorAdapter mg = new GeneratorAdapter(modifiers,
asmMethod,
null,
getTypes(method.getExceptionTypes()),
cw);
// copy annotations
for (Annotation annotation : method.getDeclaredAnnotations())
{
mg.visitAnnotation(Type.getDescriptor(annotation.annotationType()), true).visitEnd();
}
mg.visitCode();
Label tryBlockStart = mg.mark();
mg.loadThis();
mg.getField(proxyType, FIELDNAME_INVOCATION_HANDLER, TYPE_DELTA_SPIKE_PROXY_INVOCATION_HANDLER);
mg.loadThis();
loadCurrentMethod(mg, method, methodType);
loadArguments(mg, method, methodType);
mg.invokeVirtual(TYPE_DELTA_SPIKE_PROXY_INVOCATION_HANDLER,
Method.getMethod("Object invoke(Object, java.lang.reflect.Method, Object[])"));
// cast the result
mg.unbox(methodType.getReturnType());
// build try catch
Label tryBlockEnd = mg.mark();
// push return
mg.returnValue();
// catch runtime exceptions and rethrow it
Label rethrow = mg.mark();
mg.visitVarInsn(Opcodes.ASTORE, 1);
mg.visitVarInsn(Opcodes.ALOAD, 1);
mg.throwException();
mg.visitTryCatchBlock(tryBlockStart, tryBlockEnd, rethrow, Type.getInternalName(RuntimeException.class));
// catch checked exceptions and rethrow it
boolean throwableCatched = false;
if (!exceptionsToCatch.isEmpty())
{
rethrow = mg.mark();
mg.visitVarInsn(Opcodes.ASTORE, 1);
mg.visitVarInsn(Opcodes.ALOAD, 1);
mg.throwException();
// catch declared exceptions and rethrow it...
for (Type exceptionType : exceptionsToCatch)
{
if (exceptionType.getClassName().equals(Throwable.class.getName()))
{
throwableCatched = true;
}
mg.visitTryCatchBlock(tryBlockStart, tryBlockEnd, rethrow, exceptionType.getInternalName());
}
}
// if throwable isn't alreached cachted, catch it and wrap it with an UndeclaredThrowableException and throw it
if (!throwableCatched)
{
Type uteType = Type.getType(UndeclaredThrowableException.class);
Label wrapAndRethrow = mg.mark();
mg.visitVarInsn(Opcodes.ASTORE, 1);
mg.newInstance(uteType);
mg.dup();
mg.visitVarInsn(Opcodes.ALOAD, 1);
mg.invokeConstructor(uteType,
Method.getMethod("void <init>(java.lang.Throwable)"));
mg.throwException();
mg.visitTryCatchBlock(tryBlockStart, tryBlockEnd, wrapAndRethrow, Type.getInternalName(Throwable.class));
}
// finish the method
mg.endMethod();
mg.visitMaxs(12, 12);
mg.visitEnd();
}