Example usage for org.objectweb.asm ClassVisitor ClassVisitor

List of usage examples for org.objectweb.asm ClassVisitor ClassVisitor

Introduction

In this page you can find the example usage for org.objectweb.asm ClassVisitor ClassVisitor.

Prototype

public ClassVisitor(final int api, final ClassVisitor classVisitor) 

Source Link

Document

Constructs a new ClassVisitor .

Usage

From source file:Java6to2.java

License:Open Source License

private static byte[] transform(InputStream classfile) throws IOException {
    ClassReader cr = new ClassReader(classfile);
    ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
    ClassVisitor cv = new ClassVisitor(ASM7, cw) {
        String internalName;//w w w  . j a  v  a2 s.c  o m
        boolean classLookupMethodGenerated;
        Set fieldsGenerated = new HashSet();

        public void visit(int version, int access, String name, String signature, String superName,
                String[] interfaces) {
            /* Change class file version to 1.2 */
            cv.visit(V1_2, access, name, signature, superName, interfaces);
            this.internalName = name;
        }

        /**
         * Generates the synthetic "class$" method, used to lookup classes via Class.forName(). This uses the exact same code as does JDK8 javac for target 1.2.
         */
        void generateSyntheticClassLookupMethod() {
            MethodVisitor mv = cv.visitMethod(ACC_PRIVATE | ACC_STATIC | ACC_SYNTHETIC, "class$",
                    "(Ljava/lang/String;)Ljava/lang/Class;", null, null);
            {
                Label start = new Label();
                Label end = new Label();
                Label handler = new Label();
                mv.visitTryCatchBlock(start, end, handler, "java/lang/ClassNotFoundException");
                mv.visitLabel(start);
                mv.visitVarInsn(ALOAD, 0);
                mv.visitMethodInsn(INVOKESTATIC, "java/lang/Class", "forName",
                        "(Ljava/lang/String;)Ljava/lang/Class;", false);
                mv.visitLabel(end);
                mv.visitInsn(ARETURN);
                mv.visitLabel(handler);
                mv.visitVarInsn(ASTORE, 1);
                mv.visitTypeInsn(NEW, "java/lang/NoClassDefFoundError");
                mv.visitInsn(DUP);
                mv.visitMethodInsn(INVOKESPECIAL, "java/lang/NoClassDefFoundError", "<init>", "()V", false);
                mv.visitVarInsn(ALOAD, 1);
                mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/NoClassDefFoundError", "initCause",
                        "(Ljava/lang/Throwable;)Ljava/lang/Throwable;", false);
                mv.visitInsn(ATHROW);
            }
            mv.visitMaxs(2, 2);
            mv.visitEnd();
        }

        public MethodVisitor visitMethod(int access, String name, String desc, String signature,
                String[] exceptions) {
            MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
            final ClassVisitor cv = this.cv;
            return new MethodVisitor(ASM7, mv) {
                /**
                 * Intercepts class instantiations to see whether they instantiate a StringBuilder. Those instructions were generated by javac for string concatenations. But
                 * StringBuilder is not available on JRE1.2, so we just replace it with StringBuffer.
                 */
                public void visitTypeInsn(int opcode, String type) {
                    if (opcode == NEW && "java/lang/StringBuilder".equals(type)) {
                        mv.visitTypeInsn(opcode, "java/lang/StringBuffer");
                    } else {
                        mv.visitTypeInsn(opcode, type);
                    }
                }

                /**
                 * Intercepts method invocations to see whether they do something with StringBuilder. Those instructions were generated by javac for string concatenations. But
                 * StringBuilder is not available on JRE1.2, so we just replace it with StringBuffer.
                 */
                public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
                    if ("java/lang/StringBuilder".equals(owner)) {
                        mv.visitMethodInsn(opcode, "java/lang/StringBuffer", name,
                                desc.replace("java/lang/StringBuilder", "java/lang/StringBuffer"), itf);
                    } else {
                        mv.visitMethodInsn(opcode, owner, name, desc, itf);
                    }
                }

                /**
                 * Intercepts LDC instructions and check whether they are used to load a class. This is not supported on Java 1.2, so we convert it to the same code used by the
                 * JDK8 javac:
                 * <ul>
                 * <li>create synthetic fields holding the resolved class objects
                 * <li>create a synthetic method called "class$" which does Class.forName
                 * </ul>
                 */
                public void visitLdcInsn(Object cst) {
                    if (cst instanceof Type) {
                        Type t = (Type) cst;
                        String syntheticField = "class$"
                                + t.getInternalName().replace('/', '$').replace("[", "");
                        if (!classLookupMethodGenerated) {
                            /* Emit the synthetic "class$" method, used to lookup classes via Class.forName() */
                            generateSyntheticClassLookupMethod();
                            classLookupMethodGenerated = true;
                        }
                        if (!fieldsGenerated.contains(syntheticField)) {
                            /* Generate a synthetic field holding the resolved Class object */
                            cv.visitField(ACC_PRIVATE | ACC_STATIC | ACC_SYNTHETIC, syntheticField,
                                    "Ljava/lang/Class;", null, null);
                            fieldsGenerated.add(syntheticField);
                        }
                        mv.visitFieldInsn(GETSTATIC, internalName, syntheticField, "Ljava/lang/Class;");
                        Label nonNull = new Label();
                        mv.visitJumpInsn(IFNONNULL, nonNull);
                        mv.visitLdcInsn(t.getInternalName().replace('/', '.'));
                        mv.visitMethodInsn(INVOKESTATIC, internalName, "class$",
                                "(Ljava/lang/String;)Ljava/lang/Class;", false);
                        mv.visitInsn(DUP);
                        mv.visitFieldInsn(PUTSTATIC, internalName, syntheticField, "Ljava/lang/Class;");
                        Label cnt = new Label();
                        mv.visitJumpInsn(GOTO, cnt);
                        mv.visitLabel(nonNull);
                        mv.visitFieldInsn(GETSTATIC, internalName, syntheticField, "Ljava/lang/Class;");
                        mv.visitLabel(cnt);
                    } else {
                        mv.visitLdcInsn(cst);
                    }
                }
            };
        }
    };
    cr.accept(cv, ClassReader.SKIP_FRAMES); // <- Frames are not used in Java 1.2, so skip them
    return cw.toByteArray();
}

From source file:ch.eiafr.cojac.Agent.java

License:Apache License

/**
* This method works only with the FloatReplacerClasses class
* It instruments it to create a static initializer block to set
* all the static variables used by the agent and injected in the 
* instrumented application.//  w  ww  . j  ava  2 s.c  o m
* Warning: this is not the only place to set these variables, see class
* "CojacReferences" !
* This is used when there is more than one classloader in the application
*/
private byte[] setGlobalFields(byte[] byteCode, ClassLoader loader) {
    ClassReader cr = new ClassReader(byteCode);
    ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_FRAMES);
    ClassVisitor cv = new ClassVisitor(Opcodes.ASM5, cw) {
        @Override
        public void visit(int version, int access, String name, String signature, String superName,
                String[] interfaces) {
            super.visit(version, access, name, signature, superName, interfaces);
            MethodVisitor mv = cv.visitMethod(Opcodes.ACC_STATIC, "<clinit>", "()V", null, null);
            mv.visitLdcInsn(references.getDoubleWrapper());
            mv.visitMethodInsn(Opcodes.INVOKESTATIC, name, "setNgWrapper", "(Ljava/lang/String;)V", false);
            mv.visitLdcInsn(references.getNgWrapper());
            mv.visitMethodInsn(Opcodes.INVOKESTATIC, name, "setDoubleWrapper", "(Ljava/lang/String;)V", false);
            mv.visitLdcInsn(references.getFloatWrapper());
            mv.visitMethodInsn(Opcodes.INVOKESTATIC, name, "setFloatWrapper", "(Ljava/lang/String;)V", false);
            mv.visitLdcInsn(references.getBigDecimalPrecision());
            mv.visitMethodInsn(Opcodes.INVOKESTATIC, name, "setBigDecimalPrecision", "(I)V", false);
            mv.visitLdcInsn(references.getStabilityThreshold());
            mv.visitMethodInsn(Opcodes.INVOKESTATIC, name, "setStabilityThreshold", "(D)V", false);
            mv.visitLdcInsn(references.getCheckUnstableComparisons() ? 1 : 0);
            mv.visitMethodInsn(Opcodes.INVOKESTATIC, name, "setCheckUnstableComparisons", "(Z)V", false);
            mv.visitInsn(Opcodes.RETURN);
            mv.visitMaxs(0, 0);
        }
    };
    cr.accept(cv, ClassReader.EXPAND_FRAMES);
    return cw.toByteArray();
}

From source file:ch.raffael.contracts.processor.cel.skeletons.SkeletonClassLoader.java

License:Apache License

@Override
protected Class<?> findClass(String className) throws ClassNotFoundException {
    byte[] byteCode;
    try {/*w w  w . j  a va 2s.c  om*/
        byteCode = classFileLoader.loadClassFile(className);
    } catch (IOException e) {
        throw new ClassNotFoundException("I/O error loading class file for " + className, e);
    }
    if (byteCode == null) {
        throw new ClassNotFoundException(className);
    }
    ClassReader reader = new ClassReader(byteCode);
    ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
    ImmutableMap.Builder<Method, Integer> lineNumbers = ImmutableBiMap.builder();
    reader.accept(new ClassVisitor(ASM5, writer) {
        @Override
        public MethodVisitor visitMethod(int access, String name, String desc, String signature,
                String[] exceptions) {
            if (name.equals("<clinit>")) {
                return null;
            } else {
                return new SkeletonMethodVisitor(super.visitMethod(access, name, desc, signature, exceptions),
                        access, name, desc, className) {
                    @Override
                    public void visitEnd() {
                        if (getLineNumber() >= 0) {
                            lineNumbers.put(new Method(name, desc), getLineNumber());
                        }
                    }
                };
            }
        }
    }, 0);
    byte[] skeletonByteCode = writer.toByteArray();
    Class<?> skeletonClass = defineClass(className, skeletonByteCode, 0, skeletonByteCode.length);
    this.lineNumbers.put(skeletonClass, lineNumbers.build());
    return skeletonClass;
}

From source file:cn.academy.core.asm.APITransformerClient.java

License:Open Source License

@Override
public byte[] transform(String n1, String n2, byte[] data) {

    if (n1.equals("net.minecraft.client.renderer.ItemRenderer")) {
        System.out.println("Transforming " + n1 + ", " + n2);
        ClassReader cr = new ClassReader(data);
        ClassWriter cw = new ClassWriter(Opcodes.ASM4);
        ClassVisitor cv = new ClassVisitor(Opcodes.ASM4, cw) {

            @Override//www  .  j a v  a  2 s . c  o m
            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("renderItemInFirstPerson")) {
                    return new FPSkillEffect(mv);
                } else if (name.equals("renderItem") && desc
                        .equals("(Lnet/minecraft/entity/EntityLivingBase;" + "Lnet/minecraft/item/ItemStack;"
                                + "ILnet/minecraftforge/client/IItemRenderer$ItemRenderType;)V")) {
                    System.out.println("Injecting renderItem");
                    return new TPSkillEffect(mv);
                }
                return mv;
            }

        };

        cr.accept(cv, 0);
        return cw.toByteArray();
    }
    return data;
}

From source file:co.cask.cdap.app.runtime.spark.SparkRunnerClassLoader.java

License:Apache License

/**
 * Defines the DStreamGraph class by rewriting calls to parallel array with a call to
 * SparkRuntimeUtils#setTaskSupport(ParArray).
 *///w  w w. ja v a 2 s  . co  m
private Class<?> defineDStreamGraph(String name, InputStream byteCodeStream) throws IOException {
    ClassReader cr = new ClassReader(byteCodeStream);
    ClassWriter cw = new ClassWriter(0);

    cr.accept(new ClassVisitor(Opcodes.ASM5, cw) {
        @Override
        public MethodVisitor visitMethod(int access, String name, String desc, String signature,
                String[] exceptions) {
            MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
            return new MethodVisitor(Opcodes.ASM5, mv) {
                @Override
                public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
                    super.visitMethodInsn(opcode, owner, name, desc, itf);
                    // If detected call to ArrayBuffer.par(), set the TaskSupport to avoid thread leak.
                    //INVOKEVIRTUAL scala/collection/mutable/ ArrayBuffer.par ()Lscala/collection/parallel/mutable/ParArray;
                    Type returnType = Type.getReturnType(desc);
                    if (opcode == Opcodes.INVOKEVIRTUAL && name.equals("par")
                            && owner.equals("scala/collection/mutable/ArrayBuffer")
                            && returnType.getClassName().equals("scala.collection.parallel.mutable.ParArray")) {
                        super.visitMethodInsn(Opcodes.INVOKESTATIC, SPARK_RUNTIME_UTILS_TYPE.getInternalName(),
                                "setTaskSupport", Type.getMethodDescriptor(returnType, returnType), false);
                    }
                }
            };
        }
    }, ClassReader.EXPAND_FRAMES);

    byte[] byteCode = cw.toByteArray();
    return defineClass(name, byteCode, 0, byteCode.length);
}

From source file:co.cask.cdap.app.runtime.spark.SparkRunnerClassLoader.java

License:Apache License

/**
 * Rewrites the constructors who don't delegate to other constructor with the given {@link ConstructorRewriter}
 * and define the class./* www.ja v a2 s .c  om*/
 *
 * @param classType type of the class to be defined
 * @param byteCodeStream {@link InputStream} for reading the original bytecode of the class
 * @param rewriter a {@link ConstructorRewriter} for rewriting the constructor
 * @return a defined Class
 */
private Class<?> rewriteConstructorAndDefineClass(final Type classType, InputStream byteCodeStream,
        final ConstructorRewriter rewriter) throws IOException {
    ClassReader cr = new ClassReader(byteCodeStream);
    ClassWriter cw = new ClassWriter(0);

    cr.accept(new ClassVisitor(Opcodes.ASM5, cw) {

        @Override
        public MethodVisitor visitMethod(int access, String name, String desc, String signature,
                String[] exceptions) {
            // Call super so that the method signature is registered with the ClassWriter (parent)
            MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);

            // We only attempt to rewrite constructor
            if (!"<init>".equals(name)) {
                return mv;
            }

            return new AdviceAdapter(Opcodes.ASM5, mv, access, name, desc) {

                boolean calledThis;

                @Override
                public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
                    // See if in this constructor it is calling other constructor (this(..)).
                    calledThis = calledThis || (opcode == Opcodes.INVOKESPECIAL
                            && Type.getObjectType(owner).equals(classType) && name.equals("<init>")
                            && Type.getReturnType(desc).equals(Type.VOID_TYPE));
                    super.visitMethodInsn(opcode, owner, name, desc, itf);
                }

                @Override
                protected void onMethodExit(int opcode) {
                    if (calledThis) {
                        // For constructors that call this(), we don't need to generate a call to SparkContextCache
                        return;
                    }
                    // Add a call to SparkContextCache.setContext() for the normal method return path
                    if (opcode == RETURN) {
                        rewriter.onMethodExit(this);
                    }
                }
            };
        }
    }, ClassReader.EXPAND_FRAMES);

    byte[] byteCode = cw.toByteArray();
    return defineClass(classType.getClassName(), byteCode, 0, byteCode.length);
}

From source file:co.cask.cdap.app.runtime.spark.SparkRunnerClassLoader.java

License:Apache License

/**
 * Defines a class by rewriting all calls to {@link System#setProperty(String, String)} to
 * {@link SparkRuntimeEnv#setProperty(String, String)}.
 *
 * @param name name of the class to define
 * @param byteCodeStream {@link InputStream} for reading in the original bytecode.
 * @return a defined class//from  w w w  .j  a  va  2  s  .  c  om
 */
private Class<?> rewriteSetPropertiesAndDefineClass(String name, InputStream byteCodeStream)
        throws IOException {
    final Type systemType = Type.getType(System.class);
    ClassReader cr = new ClassReader(byteCodeStream);
    ClassWriter cw = new ClassWriter(0);

    cr.accept(new ClassVisitor(Opcodes.ASM5, cw) {
        @Override
        public MethodVisitor visitMethod(int access, String name, String desc, String signature,
                String[] exceptions) {
            MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
            return new MethodVisitor(Opcodes.ASM5, mv) {
                @Override
                public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
                    // If we see a call to System.setProperty, change it to SparkRuntimeEnv.setProperty
                    if (opcode == Opcodes.INVOKESTATIC && name.equals("setProperty")
                            && owner.equals(systemType.getInternalName())) {
                        super.visitMethodInsn(opcode, SPARK_RUNTIME_ENV_TYPE.getInternalName(), name, desc,
                                false);
                    } else {
                        super.visitMethodInsn(opcode, owner, name, desc, itf);
                    }
                }
            };
        }
    }, ClassReader.EXPAND_FRAMES);

    byte[] byteCode = cw.toByteArray();
    return defineClass(name, byteCode, 0, byteCode.length);
}

From source file:co.cask.cdap.app.runtime.spark.SparkRunnerClassLoader.java

License:Apache License

/**
 * Define the akka.remote.Remoting by rewriting usages of scala.concurrent.ExecutionContext.Implicits.global
 * to Remoting.system().dispatcher() in the shutdown() method for fixing the Akka thread/permgen leak bug in
 * https://github.com/akka/akka/issues/17729
 *///w ww .j av a2s .  c o m
private Class<?> defineAkkaRemoting(String name, InputStream byteCodeStream)
        throws IOException, ClassNotFoundException {
    final Type dispatcherReturnType = determineAkkaDispatcherReturnType();
    if (dispatcherReturnType == null) {
        LOG.warn("Failed to determine ActorSystem.dispatcher() return type. "
                + "No rewriting of akka.remote.Remoting class. ClassLoader leakage might happen in SDK.");
        return findClass(name);
    }

    ClassReader cr = new ClassReader(byteCodeStream);
    ClassWriter cw = new ClassWriter(0);

    cr.accept(new ClassVisitor(Opcodes.ASM5, cw) {
        @Override
        public MethodVisitor visitMethod(int access, String name, String desc, String signature,
                String[] exceptions) {
            // Call super so that the method signature is registered with the ClassWriter (parent)
            MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);

            // Only rewrite the shutdown() method
            if (!"shutdown".equals(name)) {
                return mv;
            }

            return new MethodVisitor(Opcodes.ASM5, mv) {
                @Override
                public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
                    // Detect if it is making call "import scala.concurrent.ExecutionContext.Implicits.global",
                    // which translate to Java code as
                    // scala.concurrent.ExecutionContext$Implicits$.MODULE$.global()
                    // hence as bytecode
                    // GETSTATIC scala/concurrent/ExecutionContext$Implicits$.MODULE$ :
                    //           Lscala/concurrent/ExecutionContext$Implicits$;
                    // INVOKEVIRTUAL scala/concurrent/ExecutionContext$Implicits$.global
                    //           ()Lscala/concurrent/ExecutionContextExecutor;
                    if (opcode == Opcodes.INVOKEVIRTUAL && "global".equals(name)
                            && "scala/concurrent/ExecutionContext$Implicits$".equals(owner)
                            && Type.getMethodDescriptor(EXECUTION_CONTEXT_EXECUTOR_TYPE).equals(desc)) {
                        // Discard the GETSTATIC result from the stack by popping it
                        super.visitInsn(Opcodes.POP);
                        // Make the call "import system.dispatch", which translate to Java code as
                        // this.system().dispatcher()
                        // hence as bytecode
                        // ALOAD 0 (load this)
                        // INVOKEVIRTUAL akka/remote/Remoting.system ()Lakka/actor/ExtendedActorSystem;
                        // INVOKEVIRTUAL akka/actor/ExtendedActorSystem.dispatcher ()Lscala/concurrent/ExecutionContextExecutor;
                        Type extendedActorSystemType = Type.getObjectType("akka/actor/ExtendedActorSystem");
                        super.visitVarInsn(Opcodes.ALOAD, 0);
                        super.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "akka/remote/Remoting", "system",
                                Type.getMethodDescriptor(extendedActorSystemType), false);
                        super.visitMethodInsn(Opcodes.INVOKEVIRTUAL, extendedActorSystemType.getInternalName(),
                                "dispatcher", Type.getMethodDescriptor(dispatcherReturnType), false);
                    } else {
                        // For other instructions, just call parent to deal with it
                        super.visitMethodInsn(opcode, owner, name, desc, itf);
                    }
                }
            };
        }
    }, ClassReader.EXPAND_FRAMES);

    byte[] byteCode = cw.toByteArray();
    return defineClass(name, byteCode, 0, byteCode.length);
}

From source file:co.cask.cdap.app.runtime.spark.SparkRunnerClassLoader.java

License:Apache License

/**
 * Defines the org.apache.spark.deploy.yarn.Client class with rewriting of the createConfArchive method to
 * workaround the SPARK-13441 bug./*from w w  w  . j  a v a 2  s.com*/
 */
private Class<?> defineClient(String name, InputStream createConfArchive)
        throws IOException, ClassNotFoundException {
    // We only need to rewrite if listing either HADOOP_CONF_DIR or YARN_CONF_DIR return null.
    boolean needRewrite = false;
    for (String env : ImmutableList.of("HADOOP_CONF_DIR", "YARN_CONF_DIR")) {
        String value = System.getenv(env);
        if (value != null) {
            File path = new File(value);
            if (path.isDirectory() && path.listFiles() == null) {
                needRewrite = true;
                break;
            }
        }
    }

    // If rewrite is not needed
    if (!needRewrite) {
        return findClass(name);
    }

    ClassReader cr = new ClassReader(createConfArchive);
    ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
    cr.accept(new ClassVisitor(Opcodes.ASM5, cw) {
        @Override
        public MethodVisitor visitMethod(final int access, final String name, final String desc,
                String signature, String[] exceptions) {
            MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);

            // Only rewrite the createConfArchive method
            if (!"createConfArchive".equals(name)) {
                return mv;
            }

            // Check if it's a recognizable return type.
            // Spark 1.5+ return type is File
            boolean isReturnFile = Type.getReturnType(desc).equals(Type.getType(File.class));
            Type optionType = Type.getObjectType("scala/Option");
            if (!isReturnFile) {
                // Spark 1.4 return type is Option<File>
                if (!Type.getReturnType(desc).equals(optionType)) {
                    // Unknown type. Not going to modify the code.
                    return mv;
                }
            }

            // Generate this for Spark 1.5+
            // return SparkRuntimeUtils.createConfArchive(this.sparkConf, SPARK_CONF_FILE,
            //                                            LOCALIZED_CONF_DIR, LOCALIZED_CONF_DIR_ZIP);
            // Generate this for Spark 1.4
            // return Option.apply(SparkRuntimeUtils.createConfArchive(this.sparkConf, SPARK_CONF_FILE,
            //                                                         LOCALIZED_CONF_DIR, LOCALIZED_CONF_DIR_ZIP));
            GeneratorAdapter mg = new GeneratorAdapter(mv, access, name, desc);

            // load this.sparkConf to the stack
            mg.loadThis();
            mg.getField(Type.getObjectType("org/apache/spark/deploy/yarn/Client"), "sparkConf",
                    SPARK_CONF_TYPE);

            // push three constants to the stack
            mg.visitLdcInsn(SPARK_CONF_FILE);
            mg.visitLdcInsn(LOCALIZED_CONF_DIR);
            mg.visitLdcInsn(LOCALIZED_CONF_DIR_ZIP);

            // call SparkRuntimeUtils.createConfArchive, return a File and leave it in stack
            Type stringType = Type.getType(String.class);
            mg.invokeStatic(SPARK_RUNTIME_UTILS_TYPE, new Method("createConfArchive", Type.getType(File.class),
                    new Type[] { SPARK_CONF_TYPE, stringType, stringType, stringType }));
            if (isReturnFile) {
                // Spark 1.5+ return type is File, hence just return the File from the stack
                mg.returnValue();
                mg.endMethod();
            } else {
                // Spark 1.4 return type is Option<File>
                // return Option.apply(<file from stack>);
                // where the file is actually just popped from the stack
                mg.invokeStatic(optionType,
                        new Method("apply", optionType, new Type[] { Type.getType(Object.class) }));
                mg.checkCast(optionType);
                mg.returnValue();
                mg.endMethod();
            }

            return null;
        }
    }, ClassReader.EXPAND_FRAMES);

    byte[] byteCode = cw.toByteArray();
    return defineClass(name, byteCode, 0, byteCode.length);
}

From source file:co.cask.cdap.explore.service.ExploreServiceUtils.java

License:Apache License

@VisibleForTesting
static File rewriteHiveAuthFactory(File sourceJar, File targetJar) throws IOException {
    try (JarFile input = new JarFile(sourceJar);
            JarOutputStream output = new JarOutputStream(new FileOutputStream(targetJar))) {
        String hiveAuthFactoryPath = HIVE_AUTHFACTORY_CLASS_NAME.replace('.', '/') + ".class";

        Enumeration<JarEntry> sourceEntries = input.entries();
        while (sourceEntries.hasMoreElements()) {
            JarEntry entry = sourceEntries.nextElement();
            output.putNextEntry(new JarEntry(entry.getName()));

            try (InputStream entryInputStream = input.getInputStream(entry)) {
                if (!hiveAuthFactoryPath.equals(entry.getName())) {
                    ByteStreams.copy(entryInputStream, output);
                    continue;
                }/*from   w  w w  . java 2  s.  c  o m*/

                try {
                    // Rewrite the bytecode of HiveAuthFactory.loginFromKeytab method to a no-op method
                    ClassReader cr = new ClassReader(entryInputStream);
                    ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
                    cr.accept(new ClassVisitor(Opcodes.ASM5, cw) {
                        @Override
                        public MethodVisitor visitMethod(final int access, final String name, final String desc,
                                String signature, String[] exceptions) {
                            MethodVisitor methodVisitor = super.visitMethod(access, name, desc, signature,
                                    exceptions);
                            if (!"loginFromKeytab".equals(name)) {
                                return methodVisitor;
                            }
                            GeneratorAdapter adapter = new GeneratorAdapter(methodVisitor, access, name, desc);
                            adapter.returnValue();

                            // VisitMaxs with 0 so that COMPUTE_MAXS from ClassWriter will compute the right values.
                            adapter.visitMaxs(0, 0);
                            return new MethodVisitor(Opcodes.ASM5) {
                            };
                        }
                    }, 0);
                    output.write(cw.toByteArray());
                } catch (Exception e) {
                    throw new IOException("Unable to generate HiveAuthFactory class", e);
                }
            }
        }

        return targetJar;
    }
}