List of usage examples for org.objectweb.asm MethodVisitor visitCode
public void visitCode()
From source file:co.paralleluniverse.fibers.instrument.InstrumentMethod.java
License:Open Source License
public void accept(MethodVisitor mv, boolean hasAnnotation) { db.log(LogLevel.INFO, "Instrumenting method %s#%s%s", className, mn.name, mn.desc); mv.visitAnnotation(ALREADY_INSTRUMENTED_DESC, true); final boolean handleProxyInvocations = HANDLE_PROXY_INVOCATIONS & hasSuspendableSuperCalls; mv.visitCode(); Label lMethodStart = new Label(); Label lMethodStart2 = new Label(); Label lMethodEnd = new Label(); Label lCatchSEE = new Label(); Label lCatchUTE = new Label(); Label lCatchAll = new Label(); Label[] lMethodCalls = new Label[numCodeBlocks - 1]; for (int i = 1; i < numCodeBlocks; i++) lMethodCalls[i - 1] = new Label(); mv.visitInsn(Opcodes.ACONST_NULL);// w w w .j a va2s . c o m mv.visitVarInsn(Opcodes.ASTORE, lvarInvocationReturnValue); // if (verifyInstrumentation) { // mv.visitInsn(Opcodes.ICONST_0); // mv.visitVarInsn(Opcodes.ISTORE, lvarSuspendableCalled); // } mv.visitTryCatchBlock(lMethodStart, lMethodEnd, lCatchSEE, EXCEPTION_NAME); if (handleProxyInvocations) mv.visitTryCatchBlock(lMethodStart, lMethodEnd, lCatchUTE, UNDECLARED_THROWABLE_NAME); // Prepare visitTryCatchBlocks for InvocationTargetException. // With reflective invocations, the SuspendExecution exception will be wrapped in InvocationTargetException. We need to catch it and unwrap it. // Note that the InvocationTargetException will be regenrated on every park, adding further overhead on top of the reflective call. // This must be done here, before all other visitTryCatchBlock, because the exception's handler // will be matched according to the order of in which visitTryCatchBlock has been called. Earlier calls take precedence. Label[][] refInvokeTryCatch = new Label[numCodeBlocks - 1][]; for (int i = 1; i < numCodeBlocks; i++) { FrameInfo fi = codeBlocks[i]; AbstractInsnNode in = mn.instructions.get(fi.endInstruction); if (mn.instructions.get(fi.endInstruction) instanceof MethodInsnNode) { MethodInsnNode min = (MethodInsnNode) in; if (isReflectInvocation(min.owner, min.name)) { Label[] ls = new Label[3]; for (int k = 0; k < 3; k++) ls[k] = new Label(); refInvokeTryCatch[i - 1] = ls; mv.visitTryCatchBlock(ls[0], ls[1], ls[2], "java/lang/reflect/InvocationTargetException"); } } } for (Object o : mn.tryCatchBlocks) { TryCatchBlockNode tcb = (TryCatchBlockNode) o; if (EXCEPTION_NAME.equals(tcb.type) && !hasAnnotation) // we allow catch of SuspendExecution in method annotated with @Suspendable. throw new UnableToInstrumentException("catch for SuspendExecution", className, mn.name, mn.desc); if (handleProxyInvocations && UNDECLARED_THROWABLE_NAME.equals(tcb.type)) // we allow catch of SuspendExecution in method annotated with @Suspendable. throw new UnableToInstrumentException("catch for UndeclaredThrowableException", className, mn.name, mn.desc); // if (INTERRUPTED_EXCEPTION_NAME.equals(tcb.type)) // throw new UnableToInstrumentException("catch for " + InterruptedException.class.getSimpleName(), className, mn.name, mn.desc); tcb.accept(mv); } if (mn.visibleParameterAnnotations != null) dumpParameterAnnotations(mv, mn.visibleParameterAnnotations, true); if (mn.invisibleParameterAnnotations != null) dumpParameterAnnotations(mv, mn.invisibleParameterAnnotations, false); if (mn.visibleAnnotations != null) { for (Object o : mn.visibleAnnotations) { AnnotationNode an = (AnnotationNode) o; an.accept(mv.visitAnnotation(an.desc, true)); } } mv.visitTryCatchBlock(lMethodStart, lMethodEnd, lCatchAll, null); mv.visitMethodInsn(Opcodes.INVOKESTATIC, STACK_NAME, "getStack", "()L" + STACK_NAME + ";"); mv.visitInsn(Opcodes.DUP); mv.visitVarInsn(Opcodes.ASTORE, lvarStack); // println(mv, "STACK: ", lvarStack); // dumpStack(mv); if (DUAL) { mv.visitJumpInsn(Opcodes.IFNULL, lMethodStart); mv.visitVarInsn(Opcodes.ALOAD, lvarStack); } emitStoreResumed(mv, true); // we'll assume we have been resumed mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, STACK_NAME, "nextMethodEntry", "()I"); mv.visitTableSwitchInsn(1, numCodeBlocks - 1, lMethodStart2, lMethodCalls); mv.visitLabel(lMethodStart2); // the following code handles the case of an instrumented method called not as part of a suspendable code path // isFirstInStack will return false in that case. mv.visitVarInsn(Opcodes.ALOAD, lvarStack); mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, STACK_NAME, "isFirstInStackOrPushed", "()Z"); mv.visitJumpInsn(Opcodes.IFNE, lMethodStart); // if true mv.visitInsn(Opcodes.ACONST_NULL); mv.visitVarInsn(Opcodes.ASTORE, lvarStack); mv.visitLabel(lMethodStart); emitStoreResumed(mv, false); // no, we have not been resumed dumpCodeBlock(mv, 0, 0); for (int i = 1; i < numCodeBlocks; i++) { FrameInfo fi = codeBlocks[i]; MethodInsnNode min = (MethodInsnNode) (mn.instructions.get(fi.endInstruction)); if (isYieldMethod(min.owner, min.name)) { // special case - call to yield if (min.getOpcode() != Opcodes.INVOKESTATIC) throw new UnableToInstrumentException("invalid call to suspending method.", className, mn.name, mn.desc); final int numYieldArgs = TypeAnalyzer.getNumArguments(min.desc); final boolean yieldReturnsValue = (Type.getReturnType(min.desc) != Type.VOID_TYPE); emitStoreState(mv, i, fi, numYieldArgs); // we preserve the arguments for the call to yield on the operand stack emitStoreResumed(mv, false); // we have not been resumed // emitSuspendableCalled(mv); min.accept(mv); // we call the yield method if (yieldReturnsValue) mv.visitInsn(Opcodes.POP); // we ignore the returned value... mv.visitLabel(lMethodCalls[i - 1]); // we resume AFTER the call final Label afterPostRestore = new Label(); mv.visitVarInsn(Opcodes.ILOAD, lvarResumed); mv.visitJumpInsn(Opcodes.IFEQ, afterPostRestore); emitPostRestore(mv); mv.visitLabel(afterPostRestore); emitRestoreState(mv, i, fi, numYieldArgs); if (yieldReturnsValue) mv.visitVarInsn(Opcodes.ILOAD, lvarResumed); // ... and replace the returned value with the value of resumed dumpCodeBlock(mv, i, 1); // skip the call } else { final Label lbl = new Label(); if (DUAL) { mv.visitVarInsn(Opcodes.ALOAD, lvarStack); mv.visitJumpInsn(Opcodes.IFNULL, lbl); } // normal case - call to a suspendable method - resume before the call emitStoreState(mv, i, fi, 0); emitStoreResumed(mv, false); // we have not been resumed // emitPreemptionPoint(mv, PREEMPTION_CALL); mv.visitLabel(lMethodCalls[i - 1]); emitRestoreState(mv, i, fi, 0); if (DUAL) mv.visitLabel(lbl); if (isReflectInvocation(min.owner, min.name)) { // We catch the InvocationTargetException and unwrap it if it wraps a SuspendExecution exception. Label[] ls = refInvokeTryCatch[i - 1]; final Label startTry = ls[0]; final Label endTry = ls[1]; final Label startCatch = ls[2]; final Label endCatch = new Label(); final Label notSuspendExecution = new Label(); // mv.visitTryCatchBlock(startTry, endTry, startCatch, "java/lang/reflect/InvocationTargetException"); mv.visitLabel(startTry); // try { min.accept(mv); // method.invoke() mv.visitVarInsn(Opcodes.ASTORE, lvarInvocationReturnValue); // save return value mv.visitLabel(endTry); // } mv.visitJumpInsn(Opcodes.GOTO, endCatch); mv.visitLabel(startCatch); // catch(InvocationTargetException ex) { mv.visitInsn(Opcodes.DUP); mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Throwable", "getCause", "()Ljava/lang/Throwable;"); mv.visitTypeInsn(Opcodes.INSTANCEOF, EXCEPTION_NAME); mv.visitJumpInsn(Opcodes.IFEQ, notSuspendExecution); mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Throwable", "getCause", "()Ljava/lang/Throwable;"); mv.visitLabel(notSuspendExecution); mv.visitInsn(Opcodes.ATHROW); mv.visitLabel(endCatch); mv.visitVarInsn(Opcodes.ALOAD, lvarInvocationReturnValue); // restore return value dumpCodeBlock(mv, i, 1); // skip the call } else { // emitSuspendableCalled(mv); dumpCodeBlock(mv, i, 0); } } } mv.visitLabel(lMethodEnd); if (handleProxyInvocations) { mv.visitLabel(lCatchUTE); mv.visitInsn(Opcodes.DUP); // println(mv, "CTCH: "); mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Throwable", "getCause", "()Ljava/lang/Throwable;"); // println(mv, "CAUSE: "); mv.visitTypeInsn(Opcodes.INSTANCEOF, EXCEPTION_NAME); mv.visitJumpInsn(Opcodes.IFEQ, lCatchAll); mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Throwable", "getCause", "()Ljava/lang/Throwable;"); mv.visitJumpInsn(Opcodes.GOTO, lCatchSEE); } mv.visitLabel(lCatchAll); emitPopMethod(mv); mv.visitLabel(lCatchSEE); // println(mv, "THROW: "); mv.visitInsn(Opcodes.ATHROW); // rethrow shared between catchAll and catchSSE if (mn.localVariables != null) { for (Object o : mn.localVariables) ((LocalVariableNode) o).accept(mv); } mv.visitMaxs(mn.maxStack + ADD_OPERANDS, mn.maxLocals + NUM_LOCALS + additionalLocals); mv.visitEnd(); }
From source file:com.alibaba.hotswap.processor.clinit.ClinitVisitor.java
License:Open Source License
@Override public void visitEnd() { // If no clinit method, then add it if (!hasClinitMethod) { if (!isInterface) { int access = Opcodes.ACC_STATIC + Opcodes.ACC_PUBLIC; String name = HotswapConstants.HOTSWAP_CLINIT; String desc = "()V"; MethodVisitor mv = super.visitMethod(access, name, desc, null, null); if (mv != null) { mv.visitCode(); mv.visitTypeInsn(Opcodes.NEW, "java/util/concurrent/ConcurrentHashMap"); mv.visitInsn(Opcodes.DUP); mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/util/concurrent/ConcurrentHashMap", "<init>", "()V"); mv.visitFieldInsn(Opcodes.PUTSTATIC, className, HotswapConstants.STATIC_FIELD_HOLDER, "Ljava/util/concurrent/ConcurrentHashMap;"); mv.visitInsn(Opcodes.RETURN); mv.visitMaxs(2, 0);/*from w ww .ja v a 2 s . com*/ mv.visitEnd(); } generateClinit(); } else { generateDefaultClinit(); } } else { if (!isInterface) { generateClinit(); } } super.visitEnd(); }
From source file:com.alibaba.hotswap.processor.clinit.ClinitVisitor.java
License:Open Source License
/** * Generate <code><clinit></code>, call <code>__$$hotswap_clinit$$__</code> *///from ww w . j ava 2s .c o m private void generateClinit() { MethodVisitor clinit = cv.visitMethod(Opcodes.ACC_STATIC, HotswapConstants.CLINIT, "()V", null, null); if (clinit != null) { clinit.visitCode(); clinit.visitMethodInsn(Opcodes.INVOKESTATIC, className, HotswapConstants.HOTSWAP_CLINIT, "()V"); clinit.visitInsn(Opcodes.RETURN); clinit.visitMaxs(0, 0); clinit.visitEnd(); } }
From source file:com.alibaba.hotswap.processor.clinit.ClinitVisitor.java
License:Open Source License
/** * Generate <code><clinit></code> method with default body *//*w ww . ja va 2s.com*/ private void generateDefaultClinit() { MethodVisitor clinit = cv.visitMethod(Opcodes.ACC_STATIC, HotswapConstants.CLINIT, "()V", null, null); if (clinit != null) { clinit.visitCode(); clinit.visitInsn(Opcodes.RETURN); clinit.visitMaxs(0, 0); clinit.visitEnd(); } }
From source file:com.alibaba.hotswap.processor.jdk.classloader.ClassLoaderVisitor.java
License:Open Source License
@Override public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions); if (name.equals("checkCerts")) { mv.visitCode(); mv.visitInsn(Opcodes.RETURN);/*from ww w. j a v a2s .com*/ mv.visitMaxs(0, 0); mv.visitEnd(); return null; } if (name.equals("defineClass") && desc.equals("(Ljava/lang/String;[BIILjava/security/ProtectionDomain;)Ljava/lang/Class;")) { return new DefineClassMethodModifier(mv, access, name, desc); } return mv; }
From source file:com.android.build.gradle.integration.packaging.NativeSoPackagingFromJarTest.java
License:Apache License
/** * Creates a class and returns the byte[] with the class * @return/* w ww. ja v a 2 s . c o m*/ */ private static byte[] getDummyClassByteCode() { ClassWriter cw = new ClassWriter(0); FieldVisitor fv; MethodVisitor mv; AnnotationVisitor av0; cw.visit(Opcodes.V1_6, Opcodes.ACC_PUBLIC + Opcodes.ACC_SUPER, "com/foo/Foo", null, "java/lang/Object", null); mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>", "()V", null, null); mv.visitCode(); mv.visitVarInsn(Opcodes.ALOAD, 0); mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false); mv.visitInsn(Opcodes.RETURN); mv.visitMaxs(1, 1); mv.visitEnd(); mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "aaa", "()V", null, null); mv.visitCode(); mv.visitVarInsn(Opcodes.ALOAD, 0); mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "test/Aaa", "bbb", "()V", false); mv.visitInsn(Opcodes.RETURN); mv.visitMaxs(1, 1); mv.visitEnd(); mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "bbb", "()V", null, null); mv.visitCode(); mv.visitInsn(Opcodes.RETURN); mv.visitMaxs(0, 1); mv.visitEnd(); mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "ccc", "()V", null, null); mv.visitCode(); mv.visitInsn(Opcodes.RETURN); mv.visitMaxs(0, 1); mv.visitEnd(); cw.visitEnd(); return cw.toByteArray(); }
From source file:com.android.build.gradle.internal.incremental.IncrementalChangeVisitor.java
License:Apache License
/** * Turns this class into an override class that can be loaded by our custom class loader: *<ul>//w w w.j a v a 2s . co m * <li>Make the class name be OriginalName$override</li> * <li>Ensure the class derives from java.lang.Object, no other inheritance</li> * <li>Ensure the class has a public parameterless constructor that is a noop.</li> *</ul> */ @Override public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { super.visit(version, Opcodes.ACC_PUBLIC | Opcodes.ACC_SUPER, name + OVERRIDE_SUFFIX, signature, "java/lang/Object", new String[] { CHANGE_TYPE.getInternalName() }); if (DEBUG) { System.out.println(">>>>>>>> Processing " + name + "<<<<<<<<<<<<<"); } visitedClassName = name; visitedSuperName = superName; instanceToStaticDescPrefix = "(L" + visitedClassName + ";"; // Create empty constructor MethodVisitor mv = super.visitMethod(Opcodes.ACC_PUBLIC, "<init>", "()V", null, null); mv.visitCode(); mv.visitVarInsn(Opcodes.ALOAD, 0); mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false); mv.visitInsn(Opcodes.RETURN); mv.visitMaxs(0, 0); mv.visitEnd(); super.visitField(Opcodes.ACC_PUBLIC | Opcodes.ACC_SYNTHETIC | Opcodes.ACC_STATIC, "$obsolete", "Z", null, null); }
From source file:com.android.build.gradle.internal.transforms.InstantRunTransform.java
License:Apache License
/** * Use asm to generate a concrete subclass of the AppPathLoaderImpl class. * It only implements one method ://ww w . j a va 2 s .co m * String[] getPatchedClasses(); * * The method is supposed to return the list of classes that were patched in this iteration. * This will be used by the InstantRun runtime to load all patched classes and register them * as overrides on the original classes.2 class files. * * @param patchFileContents list of patched class names. * @param outputDir output directory where to generate the .class file in. */ private static void writePatchFileContents(@NonNull ImmutableList<String> patchFileContents, @NonNull File outputDir, long buildId) { ClassWriter cw = new ClassWriter(0); MethodVisitor mv; cw.visit(Opcodes.V1_6, Opcodes.ACC_PUBLIC + Opcodes.ACC_SUPER, IncrementalVisitor.APP_PATCHES_LOADER_IMPL, null, IncrementalVisitor.ABSTRACT_PATCHES_LOADER_IMPL, null); // Add the build ID to force the patch file to be repackaged. cw.visitField(Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC + Opcodes.ACC_FINAL, "BUILD_ID", "J", null, buildId); { mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>", "()V", null, null); mv.visitCode(); mv.visitVarInsn(Opcodes.ALOAD, 0); mv.visitMethodInsn(Opcodes.INVOKESPECIAL, IncrementalVisitor.ABSTRACT_PATCHES_LOADER_IMPL, "<init>", "()V", false); mv.visitInsn(Opcodes.RETURN); mv.visitMaxs(1, 1); mv.visitEnd(); } { mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "getPatchedClasses", "()[Ljava/lang/String;", null, null); mv.visitCode(); mv.visitIntInsn(Opcodes.BIPUSH, patchFileContents.size()); mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/String"); for (int index = 0; index < patchFileContents.size(); index++) { mv.visitInsn(Opcodes.DUP); mv.visitIntInsn(Opcodes.BIPUSH, index); mv.visitLdcInsn(patchFileContents.get(index)); mv.visitInsn(Opcodes.AASTORE); } mv.visitInsn(Opcodes.ARETURN); mv.visitMaxs(4, 1); mv.visitEnd(); } cw.visitEnd(); byte[] classBytes = cw.toByteArray(); File outputFile = new File(outputDir, IncrementalVisitor.APP_PATCHES_LOADER_IMPL + ".class"); try { Files.createParentDirs(outputFile); Files.write(classBytes, outputFile); } catch (IOException e) { throw new RuntimeException(e); } }
From source file:com.android.build.gradle.internal2.incremental.IncrementalChangeVisitor.java
License:Apache License
/** * Turns this class into an override class that can be loaded by our custom class loader: *<ul>/*from ww w .j a va 2s. c om*/ * <li>Make the class name be OriginalName$override</li> * <li>Ensure the class derives from java.lang.Object, no other inheritance</li> * <li>Ensure the class has a public parameterless constructor that is a noop.</li> *</ul> */ @Override public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { // TODO: modified by achellies, ?,??,?ClassClass,Opcodes.INVOKESPECIAL?super super.visit(version, Opcodes.ACC_PUBLIC | Opcodes.ACC_SUPER, name + OVERRIDE_SUFFIX, signature, superName, // TODO modified by achellies, "java/lang/Object" -> superName new String[] { CHANGE_TYPE.getInternalName() }); if (DEBUG) { System.out.println(">>>>>>>> Processing " + name + "<<<<<<<<<<<<<"); } visitedClassName = name; visitedSuperName = superName; instanceToStaticDescPrefix = "(L" + visitedClassName + ";"; // Create empty constructor MethodVisitor mv = super.visitMethod(Opcodes.ACC_PUBLIC, ByteCodeUtils.CONSTRUCTOR, "()V", null, null); mv.visitCode(); mv.visitVarInsn(Opcodes.ALOAD, 0); mv.visitMethodInsn(Opcodes.INVOKESPECIAL, superName, ByteCodeUtils.CONSTRUCTOR, "()V", // TODO modified by achellies, "java/lang/Object" -> superName false); mv.visitInsn(Opcodes.RETURN); mv.visitMaxs(0, 0); mv.visitEnd(); super.visitField(Opcodes.ACC_PUBLIC | Opcodes.ACC_SYNTHETIC | Opcodes.ACC_STATIC, "$obsolete", "Z", null, null); }
From source file:com.android.build.gradle.shrinker.TestClasses.java
License:Apache License
static byte[] emptyClass(String name) throws Exception { ClassWriter cw = new ClassWriter(0); FieldVisitor fv;/*from w ww . j a va 2 s . co m*/ MethodVisitor mv; AnnotationVisitor av0; cw.visit(V1_6, ACC_PUBLIC + ACC_SUPER, "test/" + name, null, "java/lang/Object", null); { mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null); mv.visitCode(); mv.visitVarInsn(ALOAD, 0); mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false); mv.visitInsn(RETURN); mv.visitMaxs(1, 1); mv.visitEnd(); } cw.visitEnd(); return cw.toByteArray(); }