com.android.utils.AsmUtils Java Examples
The following examples show how to use
com.android.utils.AsmUtils.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: IncrementalSupportVisitor.java From AnoleFix with MIT License | 5 votes |
/** * Add all constructors from the passed ClassNode's methods. {@see ClassNode#methods} * * @param methods the constructors already encountered in the ClassNode hierarchy * @param classNode the class to save all new methods from. * @param keepPrivateConstructors whether to keep the private constructors. */ private void addAllNewConstructors(Map<String, MethodNode> methods, ClassNode classNode, boolean keepPrivateConstructors) { //noinspection unchecked for (MethodNode method : (List<MethodNode>) classNode.methods) { if (!method.name.equals(AsmUtils.CONSTRUCTOR)) { continue; } if (!isAccessCompatibleWithInstantRun(method.access)) { continue; } if (!keepPrivateConstructors && (method.access & Opcodes.ACC_PRIVATE) != 0) { continue; } if (!classNode.name.equals(visitedClassName) && !classNode.name.equals(visitedSuperName)) { continue; } String key = classNode.name + "." + method.desc; if (methods.containsKey(key)) { continue; } methods.put(key, method); } }
Example #2
Source File: IncrementalSupportVisitor.java From AnoleFix with MIT License | 4 votes |
/** * Insert Constructor specific logic({@link ConstructorArgsRedirection} and * {@link ConstructorDelegationDetector}) for constructor redirecting or * normal method redirecting ({@link MethodRedirection}) for other methods. */ @Override public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { access = transformAccessForInstantRun(access); MethodVisitor defaultVisitor = super.visitMethod(access, name, desc, signature, exceptions); MethodNode method = getMethodByNameInClass(name, desc, classNode); // does the method use blacklisted APIs. boolean hasIncompatibleChange = InstantRunMethodVerifier.verifyMethod(method) != InstantRunVerifierStatus.COMPATIBLE; if (hasIncompatibleChange || disableRedirectionForClass || !isAccessCompatibleWithInstantRun(access) || name.equals(AsmUtils.CLASS_INITIALIZER)) { return defaultVisitor; } else { ISMethodVisitor mv = new ISMethodVisitor(defaultVisitor, access, name, desc); if (name.equals(AsmUtils.CONSTRUCTOR)) { ConstructorDelegationDetector.Constructor constructor = ConstructorDelegationDetector.deconstruct(visitedClassName, method); LabelNode start = new LabelNode(); LabelNode after = new LabelNode(); method.instructions.insert(constructor.loadThis, start); if (constructor.lineForLoad != -1) { // Record the line number from the start of LOAD_0 for uninitialized 'this'. // This allows a breakpoint to be set at the line with this(...) or super(...) // call in the constructor. method.instructions.insert(constructor.loadThis, new LineNumberNode(constructor.lineForLoad, start)); } method.instructions.insert(constructor.delegation, after); mv.addRedirection( new ConstructorArgsRedirection( start, visitedClassName, constructor.args.name + "." + constructor.args.desc, after, Type.getArgumentTypes(constructor.delegation.desc))); mv.addRedirection(new MethodRedirection(after, constructor.body.name + "." + constructor.body.desc, Type.getReturnType(desc))); } else { mv.addRedirection(new MethodRedirection( new LabelNode(mv.getStartLabel()), name + "." + desc, Type.getReturnType(desc))); } method.accept(mv); return null; } }
Example #3
Source File: IncrementalSupportVisitor.java From AnoleFix with MIT License | 4 votes |
/*** * Inserts a trampoline to this class so that the updated methods can make calls to * constructors. * <p> * <p/> * Pseudo code for this trampoline: * <code> * ClassName(Object[] args, Marker unused) { * String name = (String) args[0]; * if (name.equals( * "java/lang/ClassName.(Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;")) { * this((String)arg[1], arg[2]); * return * } * if (name.equals("SuperClassName.(Ljava/lang/String;I)V")) { * super((String)arg[1], (int)arg[2]); * return; * } * ... * StringBuilder $local1 = new StringBuilder(); * $local1.append("Method not found "); * $local1.append(name); * $local1.append(" in " $classType $super implementation"); * throw new $package/InstantReloadException($local1.toString()); * } * </code> */ private void createDispatchingThis() { // Gather all methods from itself and its superclasses to generate a giant constructor // implementation. // This will work fine as long as we don't support adding constructors to classes. final Map<String, MethodNode> uniqueMethods = new HashMap<String, MethodNode>(); addAllNewConstructors(uniqueMethods, classNode, true /*keepPrivateConstructors*/); for (ClassNode parentNode : parentNodes) { addAllNewConstructors(uniqueMethods, parentNode, false /*keepPrivateConstructors*/); } int access = Opcodes.ACC_PUBLIC | Opcodes.ACC_SYNTHETIC; Method m = new Method(AsmUtils.CONSTRUCTOR, ConstructorArgsRedirection.DISPATCHING_THIS_SIGNATURE); MethodVisitor visitor = super.visitMethod(0, m.getName(), m.getDescriptor(), null, null); final GeneratorAdapter mv = new GeneratorAdapter(access, m, visitor); mv.visitCode(); // Mark this code as redirection code Label label = new Label(); mv.visitLineNumber(0, label); // Get and store the constructor canonical name. mv.visitVarInsn(Opcodes.ALOAD, 1); mv.push(0); mv.visitInsn(Opcodes.AALOAD); mv.unbox(Type.getType("Ljava/lang/String;")); final int constructorCanonicalName = mv.newLocal(Type.getType("Ljava/lang/String;")); mv.storeLocal(constructorCanonicalName); new StringSwitch() { @Override void visitString() { mv.loadLocal(constructorCanonicalName); } @Override void visitCase(String canonicalName) { MethodNode methodNode = uniqueMethods.get(canonicalName); String owner = canonicalName.split("\\.")[0]; // Parse method arguments and mv.visitVarInsn(Opcodes.ALOAD, 0); Type[] args = Type.getArgumentTypes(methodNode.desc); int argc = 0; for (Type t : args) { mv.visitVarInsn(Opcodes.ALOAD, 1); mv.push(argc + 1); mv.visitInsn(Opcodes.AALOAD); ByteCodeUtils.unbox(mv, t); argc++; } mv.visitMethodInsn(Opcodes.INVOKESPECIAL, owner, AsmUtils.CONSTRUCTOR, methodNode.desc, false); mv.visitInsn(Opcodes.RETURN); } @Override void visitDefault() { writeMissingMessageWithHash(mv, visitedClassName); } }.visit(mv, uniqueMethods.keySet()); mv.visitMaxs(1, 3); mv.visitEnd(); }