List of usage examples for org.objectweb.asm MethodVisitor MethodVisitor
public MethodVisitor(final int api, final MethodVisitor methodVisitor)
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;/*from ww w . ja va 2 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:blue.lapis.methodremapper.RemapInvokeClassVisitor.java
License:Open Source License
@Override public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { return new MethodVisitor(ASM5, super.visitMethod(access, name, desc, signature, exceptions)) { @Override// w ww. j a v a 2s. c o m public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) { try { String mapping = remapper.getMapping(owner, name + desc); super.visitMethodInsn(opcode, owner, mapping != null ? mapping : name, desc, itf); } catch (IOException e) { throw Throwables.propagate(e); } } }; }
From source file:cn.annoreg.asm.DelegateGenerator.java
License:Open Source License
public static MethodVisitor generateStaticMethod(ClassVisitor parentClass, MethodVisitor parent, String className, String methodName, String desc, final Side side) { //This method is a little bit complicated. //We need to generate a delegate class implementing NetworkCallDelegate and a redirect //the code that originally generated here in parent, into the delegate class, //by returning a MethodVisitor under the ClassVisitor of the delegate class. //Besides, we should generate a call to NetworkCallManager into parent. //Above is the original method. Now it has a little bit change. To allow private call in //here, we need to generate the delegate method in this class instead of in a delegate class. //We make the delegate method public so that the delegate class can call it. //delegateName is a string used by both sides to identify a network-call delegate. final String delegateName = className + ":" + methodName + ":" + desc; final Type[] args = Type.getArgumentTypes(desc); final Type ret = Type.getReturnType(desc); //Check types for (Type t : args) { //TODO support these types if (!t.getDescriptor().startsWith("L") && !t.getDescriptor().startsWith("[")) { throw new RuntimeException("Unsupported argument type in network call. in method " + methodName + ", " + t.getDescriptor()); }/*w w w. java2 s . c om*/ } if (!ret.equals(Type.VOID_TYPE)) { throw new RuntimeException( "Unsupported return value type in network call. " + "Only void is supported."); } //Generate call to NetworkCallManager in parent. parent.visitCode(); //First parameter parent.visitLdcInsn(delegateName); //Second parameter: object array pushIntegerConst(parent, args.length); //array size parent.visitTypeInsn(Opcodes.ANEWARRAY, Type.getInternalName(Object.class)); for (int i = 0; i < args.length; ++i) { parent.visitInsn(Opcodes.DUP); pushIntegerConst(parent, i); parent.visitVarInsn(Opcodes.ALOAD, i); parent.visitInsn(Opcodes.AASTORE); } //Call cn.annoreg.mc.network.NetworkCallManager.onNetworkCall parent.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(NetworkCallManager.class), "onNetworkCall", Type.getMethodDescriptor(Type.VOID_TYPE, Type.getType(String.class), Type.getType(Object[].class))); parent.visitInsn(Opcodes.RETURN); parent.visitMaxs(5, args.length); parent.visitEnd(); //Create delegate object. final ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); final String delegateId = Integer.toString(delegateNextID++); final Type delegateClassType = Type.getType("cn/annoreg/asm/NetworkCallDelegate_" + delegateId); cw.visit(Opcodes.V1_5, Opcodes.ACC_PUBLIC, delegateClassType.getInternalName(), null, Type.getInternalName(Object.class), new String[] { Type.getInternalName(NetworkCallDelegate.class) }); //package cn.annoreg.asm; //class NetworkCallDelegate_? implements NetworkCallDelegate { { MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>", "()V", null, null); mv.visitCode(); mv.visitVarInsn(Opcodes.ALOAD, 0); mv.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getInternalName(Object.class), "<init>", "()V"); mv.visitInsn(Opcodes.RETURN); mv.visitMaxs(1, 1); mv.visitEnd(); } //public NetworkCallDelegate_?() {} final String delegateFunctionName = methodName + "_delegate_" + delegateId; { MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "invoke", Type.getMethodDescriptor(Type.VOID_TYPE, Type.getType(Object[].class)), null, null); mv.visitCode(); for (int i = 0; i < args.length; ++i) { mv.visitVarInsn(Opcodes.ALOAD, 1); //0 is this pushIntegerConst(mv, i); mv.visitInsn(Opcodes.AALOAD); mv.visitTypeInsn(Opcodes.CHECKCAST, args[i].getInternalName()); } mv.visitMethodInsn(Opcodes.INVOKESTATIC, //delegateClassType.getInternalName(), //changed to original class className.replace('.', '/'), delegateFunctionName, desc); mv.visitInsn(Opcodes.RETURN); mv.visitMaxs(args.length + 2, 2); mv.visitEnd(); } //@Override public void invoke(Object[] args) { // xxxx.xxxx_delegated_xxx((Type0) args[0], (Type1) args[1], ...); //} //The returned MethodVisitor will visit the original version of the method, //including its annotation, where we can get StorageOptions. return new MethodVisitor(Opcodes.ASM4, parentClass.visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC, delegateFunctionName, desc, null, null)) { //Remember storage options for each argument StorageOption.Option[] options = new StorageOption.Option[args.length]; int targetIndex = -1; StorageOption.Target.RangeOption range = StorageOption.Target.RangeOption.SINGLE; double sendRange = -1; { for (int i = 0; i < options.length; ++i) { options[i] = StorageOption.Option.NULL; //set default value } } @Override public AnnotationVisitor visitParameterAnnotation(final int parameter, String desc, boolean visible) { Type type = Type.getType(desc); if (type.equals(Type.getType(StorageOption.Data.class))) { options[parameter] = StorageOption.Option.DATA; } else if (type.equals(Type.getType(StorageOption.Instance.class))) { //INSTANCE as defualt options[parameter] = StorageOption.Option.INSTANCE; //Change to NULLABLE_INSTANCE if nullable set to true return new AnnotationVisitor(this.api, super.visitParameterAnnotation(parameter, desc, visible)) { @Override public void visit(String name, Object value) { if (name.equals("nullable")) { if ((Boolean) value == true) { options[parameter] = StorageOption.Option.NULLABLE_INSTANCE; } } super.visit(name, value); } }; } else if (type.equals(Type.getType(StorageOption.Update.class))) { options[parameter] = StorageOption.Option.UPDATE; } else if (type.equals(Type.getType(StorageOption.Null.class))) { options[parameter] = StorageOption.Option.NULL; } else if (type.equals(Type.getType(StorageOption.Target.class))) { if (!args[parameter].equals(Type.getType(EntityPlayer.class))) { throw new RuntimeException("Target annotation can only be used on EntityPlayer."); } if (targetIndex != -1) { throw new RuntimeException("You can not specify multiple targets."); } options[parameter] = StorageOption.Option.INSTANCE; targetIndex = parameter; return new AnnotationVisitor(this.api, super.visitParameterAnnotation(parameter, desc, visible)) { @Override public void visitEnum(String name, String desc, String value) { super.visitEnum(name, desc, value); range = StorageOption.Target.RangeOption.valueOf(value); } }; } else if (type.equals(Type.getType(StorageOption.RangedTarget.class))) { if (targetIndex != -1) { throw new RuntimeException("You can not specify multiple targets."); } range = null; targetIndex = parameter; return new AnnotationVisitor(this.api, super.visitParameterAnnotation(parameter, desc, visible)) { @Override public void visit(String name, Object value) { super.visit(name, value); sendRange = (double) value; } }; } return super.visitParameterAnnotation(parameter, desc, visible); } @Override public void visitEnd() { super.visitEnd(); //This is the last method in the delegate class. //Finish the class and do the registration. cw.visitEnd(); try { Class<?> clazz = classLoader.defineClass(delegateClassType.getClassName(), cw.toByteArray()); NetworkCallDelegate delegateObj = (NetworkCallDelegate) clazz.newInstance(); if (side == Side.CLIENT) { NetworkCallManager.registerClientDelegateClass(delegateName, delegateObj, options, targetIndex, range, sendRange); } else { NetworkCallManager.registerServerDelegateClass(delegateName, delegateObj, options); } } catch (Throwable e) { throw new RuntimeException("Can not create delegate for network call.", e); } } }; //public static void delegated(Type0 arg0, Type1, arg1, ...) { // //Code generated by caller. //} //} }
From source file:cn.annoreg.asm.DelegateGenerator.java
License:Open Source License
public static MethodVisitor generateNonStaticMethod(ClassVisitor parentClass, MethodVisitor parent, String className, String methodName, String desc, final Side side) { //convert desc to a non-static method form String nonstaticDesc;/*w w w .jav a 2 s. c o m*/ { Type staticType = Type.getMethodType(desc); Type retType = staticType.getReturnType(); Type[] argsType = staticType.getArgumentTypes(); Type[] argsTypeWithThis = new Type[argsType.length + 1]; argsTypeWithThis[0] = Type.getType('L' + className.replace('.', '/') + ';'); System.arraycopy(argsType, 0, argsTypeWithThis, 1, argsType.length); nonstaticDesc = Type.getMethodDescriptor(retType, argsTypeWithThis); } //delegateName is a string used by both sides to identify a network-call delegate. final String delegateName = className + ":" + methodName + ":" + desc; final Type[] args = Type.getArgumentTypes(nonstaticDesc); final Type ret = Type.getReturnType(nonstaticDesc); //Check types for (Type t : args) { //TODO support these types if (!t.getDescriptor().startsWith("L") && !t.getDescriptor().startsWith("[")) { throw new RuntimeException("Unsupported argument type in network call. "); } } if (!ret.equals(Type.VOID_TYPE)) { throw new RuntimeException( "Unsupported return value type in network call. " + "Only void is supported."); } //Generate call to NetworkCallManager in parent. parent.visitCode(); //First parameter parent.visitLdcInsn(delegateName); //Second parameter: object array pushIntegerConst(parent, args.length); //this (0) has been included parent.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object"); for (int i = 0; i < args.length; ++i) { parent.visitInsn(Opcodes.DUP); pushIntegerConst(parent, i); parent.visitVarInsn(Opcodes.ALOAD, i); parent.visitInsn(Opcodes.AASTORE); } //Call cn.annoreg.mc.network.NetworkCallManager.onNetworkCall parent.visitMethodInsn(Opcodes.INVOKESTATIC, Type.getInternalName(NetworkCallManager.class), "onNetworkCall", "(Ljava/lang/String;[Ljava/lang/Object;)V"); parent.visitInsn(Opcodes.RETURN); parent.visitMaxs(5, args.length); parent.visitEnd(); //Create delegate object. final ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); final String delegateId = Integer.toString(delegateNextID++); final Type delegateClassType = Type.getType("cn/annoreg/asm/NetworkCallDelegate_" + delegateId); cw.visit(Opcodes.V1_5, Opcodes.ACC_PUBLIC, delegateClassType.getInternalName(), null, Type.getInternalName(Object.class), new String[] { Type.getInternalName(NetworkCallDelegate.class) }); //package cn.annoreg.asm; //class NetworkCallDelegate_? implements NetworkCallDelegate { { MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>", "()V", null, null); mv.visitCode(); mv.visitVarInsn(Opcodes.ALOAD, 0); mv.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getInternalName(Object.class), "<init>", "()V"); mv.visitInsn(Opcodes.RETURN); mv.visitMaxs(1, 1); mv.visitEnd(); } //public NetworkCallDelegate_?() {} final String delegateMethodName = methodName + "_delegate_" + delegateId; { MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "invoke", Type.getMethodDescriptor(Type.VOID_TYPE, Type.getType(Object[].class)), null, null); mv.visitCode(); //check if this is null mv.visitVarInsn(Opcodes.ALOAD, 1); //0 is this pushIntegerConst(mv, 0); mv.visitInsn(Opcodes.AALOAD); Label lblEnd = new Label(); mv.visitJumpInsn(Opcodes.IFNULL, lblEnd); for (int i = 0; i < args.length; ++i) { mv.visitVarInsn(Opcodes.ALOAD, 1); //0 is this pushIntegerConst(mv, i); mv.visitInsn(Opcodes.AALOAD); mv.visitTypeInsn(Opcodes.CHECKCAST, args[i].getInternalName()); } mv.visitMethodInsn(Opcodes.INVOKESTATIC, //delegateClassType.getInternalName(), className.replace('.', '/'), delegateMethodName, nonstaticDesc); mv.visitLabel(lblEnd); mv.visitInsn(Opcodes.RETURN); mv.visitMaxs(args.length + 2, 2); mv.visitEnd(); } //@Override public void invoke(Object[] args) { // delegated((Type0) args[0], (Type1) args[1], ...); //} //The returned MethodVisitor will visit the original version of the method, //including its annotation, where we can get StorageOptions. return new MethodVisitor(Opcodes.ASM4, parentClass.visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC, delegateMethodName, nonstaticDesc, null, null)) { //Remember storage options for each argument StorageOption.Option[] options = new StorageOption.Option[args.length]; int targetIndex = -1; double sendRange = -1; StorageOption.Target.RangeOption range = StorageOption.Target.RangeOption.SINGLE; { for (int i = 0; i < options.length; ++i) { options[i] = StorageOption.Option.NULL; //set default value } options[0] = StorageOption.Option.INSTANCE; } @Override public AnnotationVisitor visitParameterAnnotation(int parameter_in_func, String desc, boolean visible) { final int parameter = parameter_in_func + 1; //skip this Type type = Type.getType(desc); if (type.equals(Type.getType(StorageOption.Data.class))) { options[parameter] = StorageOption.Option.DATA; } else if (type.equals(Type.getType(StorageOption.Instance.class))) { //INSTANCE as defualt options[parameter] = StorageOption.Option.INSTANCE; //Change to NULLABLE_INSTANCE if nullable set to true return new AnnotationVisitor(this.api, super.visitParameterAnnotation(parameter, desc, visible)) { @Override public void visit(String name, Object value) { if (name.equals("nullable")) { if ((Boolean) value == true) { options[parameter] = StorageOption.Option.NULLABLE_INSTANCE; } } super.visit(name, value); } }; } else if (type.equals(Type.getType(StorageOption.Update.class))) { options[parameter] = StorageOption.Option.UPDATE; } else if (type.equals(Type.getType(StorageOption.Null.class))) { options[parameter] = StorageOption.Option.NULL; } else if (type.equals(Type.getType(StorageOption.Target.class))) { if (!args[parameter].equals(Type.getType(EntityPlayer.class))) { throw new RuntimeException("Target annotation can only be used on EntityPlayer."); } if (targetIndex != -1) { throw new RuntimeException("You can not specify multiple targets."); } options[parameter] = StorageOption.Option.INSTANCE; targetIndex = parameter; return new AnnotationVisitor(this.api, super.visitParameterAnnotation(parameter, desc, visible)) { @Override public void visitEnum(String name, String desc, String value) { super.visitEnum(name, desc, value); range = StorageOption.Target.RangeOption.valueOf(value); } }; } else if (type.equals(Type.getType(StorageOption.RangedTarget.class))) { if (targetIndex != -1) { throw new RuntimeException("You can not specify multiple targets."); } targetIndex = parameter; range = null; return new AnnotationVisitor(this.api, super.visitParameterAnnotation(parameter, desc, visible)) { @Override public void visit(String name, Object value) { super.visit(name, value); sendRange = (double) value; } }; } return super.visitParameterAnnotation(parameter, desc, visible); } //TODO this option (from annotation) @Override public void visitEnd() { super.visitEnd(); //This is the last method in the delegate class. //Finish the class and do the registration. cw.visitEnd(); try { Class<?> clazz = classLoader.defineClass(delegateClassType.getClassName(), cw.toByteArray()); NetworkCallDelegate delegateObj = (NetworkCallDelegate) clazz.newInstance(); if (side == Side.CLIENT) { NetworkCallManager.registerClientDelegateClass(delegateName, delegateObj, options, targetIndex, range, sendRange); } else { NetworkCallManager.registerServerDelegateClass(delegateName, delegateObj, options); } } catch (Throwable e) { throw new RuntimeException("Can not create delegate for network call.", e); } } }; //public static void delegated(Type0 arg0, Type1, arg1, ...) { // //Code generated by caller. //} //} }
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). *///from w w w .j ava2 s . c om 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
/** * 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 ww w . j a v a 2s . co m */ 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 *///from w w w. ja v a 2 s . 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.paralleluniverse.common.util.ExtendedStackTrace.java
License:Open Source License
protected /*Executable*/ Member getMethod(final ExtendedStackTraceElement este) { if (este.getDeclaringClass() == null) return null; Member[] ms = getMethods(este.getDeclaringClass()); Member method = null;//from w w w. j a va 2 s .c o m for (Member m : ms) { if (este.getMethodName().equals(m.getName())) { if (method == null) method = m; else { method = null; // more than one match break; } } } if (method == null && este.getLineNumber() >= 0) { try { final AtomicReference<String> descriptor = new AtomicReference<>(); ASMUtil.accept(este.getDeclaringClass(), ClassReader.SKIP_FRAMES, new ClassVisitor(Opcodes.ASM5) { @Override public MethodVisitor visitMethod(int access, String name, final String desc, String signature, String[] exceptions) { MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions); if (descriptor.get() == null && este.getMethodName().equals(name)) { mv = new MethodVisitor(api, mv) { int minLine = Integer.MAX_VALUE, maxLine = Integer.MIN_VALUE; @Override public void visitLineNumber(int line, Label start) { if (line < minLine) minLine = line; if (line > maxLine) maxLine = line; } @Override public void visitEnd() { if (minLine <= este.getLineNumber() && maxLine >= este.getLineNumber()) descriptor.set(desc); super.visitEnd(); } }; } return mv; } }); if (descriptor.get() != null) { final String desc = descriptor.get(); for (Member m : ms) { if (este.getMethodName().equals(getName(m)) && desc.equals(getDescriptor(m))) { method = m; break; } } } } catch (Exception e) { e.printStackTrace(); } } return method; }
From source file:co.paralleluniverse.fibers.instrument.InstrumentClass.java
License:Open Source License
@Override public MethodVisitor visitMethod(final int access, final String name, final String desc, final String signature, final String[] exceptions) { SuspendableType markedSuspendable = null; if (suspendableInterface) markedSuspendable = SuspendableType.SUSPENDABLE_SUPER; if (markedSuspendable == null) markedSuspendable = classifier.isSuspendable(db, className, classEntry.getSuperName(), classEntry.getInterfaces(), name, desc, signature, exceptions); final SuspendableType setSuspendable = classEntry.check(name, desc); if (setSuspendable == null) classEntry.set(name, desc,/*from ww w .j a v a 2 s .c om*/ markedSuspendable != null ? markedSuspendable : SuspendableType.NON_SUSPENDABLE); final boolean suspendable = markedSuspendable == SuspendableType.SUSPENDABLE | setSuspendable == SuspendableType.SUSPENDABLE; if (checkAccess(access) && !isYieldMethod(className, name)) { if (isSynchronized(access)) { if (!db.isAllowMonitors()) throw new UnableToInstrumentException("synchronization", className, name, desc); else db.log(LogLevel.WARNING, "Method %s#%s%s is synchronized", className, name, desc); } if (methods == null) methods = new ArrayList<MethodNode>(); final MethodNode mn = new MethodNode(access, name, desc, signature, exceptions); // if (suspendable) { // if (db.isDebug()) // db.log(LogLevel.INFO, "Method %s#%s suspendable: %s (markedSuspendable: %s setSuspendable: %s)", className, name, suspendable, markedSuspendable, setSuspendable); // // methods.add(mn); // return mn; // this causes the mn to be initialized // } else { // look for @Suspendable or @DontInstrument annotation return new MethodVisitor(Opcodes.ASM4, mn) { private boolean susp = suspendable; private boolean commited = false; @Override public AnnotationVisitor visitAnnotation(String adesc, boolean visible) { if (adesc.equals(ANNOTATION_DESC)) susp = true; else if (adesc.equals(DONT_INSTRUMENT_ANNOTATION_DESC)) susp = false; return super.visitAnnotation(adesc, visible); } @Override public void visitCode() { commit(); super.visitCode(); } @Override public void visitEnd() { if (exception != null) return; commit(); try { super.visitEnd(); } catch (RuntimeException e) { exception = e; } } private void commit() { if (commited) return; commited = true; if (db.isDebug()) db.log(LogLevel.INFO, "Method %s#%s suspendable: %s (markedSuspendable: %s setSuspendable: %s)", className, name, susp, susp, setSuspendable); classEntry.set(name, desc, susp ? SuspendableType.SUSPENDABLE : SuspendableType.NON_SUSPENDABLE); if (susp) methods.add(mn); else { MethodVisitor _mv = makeOutMV(mn); _mv = new JSRInlinerAdapter(_mv, access, name, desc, signature, exceptions); mn.accept(new MethodVisitor(Opcodes.ASM4, _mv) { @Override public void visitEnd() { // don't call visitEnd on MV } }); // write method as-is this.mv = _mv; } } }; // } } return super.visitMethod(access, name, desc, signature, exceptions); }
From source file:co.paralleluniverse.fibers.instrument.JavaAgent.java
License:Open Source License
public static byte[] crazyClojureOnceDisable(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { if (!Boolean.parseBoolean(System.getProperty("co.paralleluniverse.pulsar.disableOnce", "false"))) return classfileBuffer; ClassReader cr = new ClassReader(classfileBuffer); ClassWriter cw = new ClassWriter(cr, 0); ClassVisitor cv = new ClassVisitor(Opcodes.ASM4, cw) { @Override// w ww . j a v a 2s. co m public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { return new MethodVisitor(api, super.visitMethod(access, name, desc, signature, exceptions)) { @Override public void visitLdcInsn(Object cst) { if (cst instanceof String && cst.equals("once")) { super.visitLdcInsn("once$disabled-by-pulsar"); } else super.visitLdcInsn(cst); } }; } }; cr.accept(cv, 0); return cw.toByteArray(); }