下面列出了怎么用org.objectweb.asm.commons.JSRInlinerAdapter的API类实例代码及写法,或者点击链接到github查看源代码。
/**
* Creates a method adapter that will instrument to original code in such a way that it can
* patch live code.
* @param access the method access flags.
* @param name the method name
* @param originalDesc the original description.
* @param newDesc the modified method description that suits the InstantRun patching algorithms
* @param signature the method signature.
* @param exceptions the exceptions thrown by the method
* @param isStatic true if the method is static, false otherwise.
* @param isConstructor true if a constructor. false otherwise.
* @return the method adapter visitor.
*/
private MethodVisitor createMethodAdapter(
int access,
String name,
String originalDesc,
String newDesc,
String signature,
String[] exceptions,
boolean isStatic,
boolean isConstructor) {
MethodVisitor methodVisitor =
super.visitMethod(access, name, originalDesc, signature, exceptions);
methodVisitor = new ISVisitor(methodVisitor, access, name, newDesc, isStatic, isConstructor);
// Install the Jsr/Ret inliner adapter, we have had reports of code still using the
// Jsr/Ret deprecated byte codes.
// see https://code.google.com/p/android/issues/detail?id=220019
return new JSRInlinerAdapter(methodVisitor, access, name, newDesc, signature, exceptions);
}
@Override
public MethodVisitor visitMethod(int access, String name, String desc,
String signature, String[] exceptions) {
if (!name.equals(methodToVisit.getName()) || !desc.equals(methodToVisit.getDesc())) {
return null;
}
if (passthroughDataflowMethodVisitor != null) {
throw new IllegalStateException("Constructing passthroughDataflowMethodVisitor twice!");
}
MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
passthroughDataflowMethodVisitor = new PassthroughDataflowMethodVisitor(
classMap, inheritanceMap, this.passthroughDataflow, serializableDecider,
api, mv, this.name, access, name, desc, signature, exceptions);
return new JSRInlinerAdapter(passthroughDataflowMethodVisitor, access, name, desc, signature, exceptions);
}
/**
* Creates a method adapter that will instrument to original code in such a way that it can
* patch live code.
* @param access the method access flags.
* @param name the method name
* @param originalDesc the original description.
* @param newDesc the modified method description that suits the InstantRun patching algorithms
* @param signature the method signature.
* @param exceptions the exceptions thrown by the method
* @param isStatic true if the method is static, false otherwise.
* @param isConstructor true if a constructor. false otherwise.
* @return the method adapter visitor.
*/
private MethodVisitor createMethodAdapter(
int access,
String name,
String originalDesc,
String newDesc,
String signature,
String[] exceptions,
boolean isStatic,
boolean isConstructor) {
MethodVisitor methodVisitor =
super.visitMethod(access, name, originalDesc, signature, exceptions);
methodVisitor = new TBIncrementalChangeVisitor.ISVisitor(methodVisitor, access, name, newDesc, isStatic, isConstructor);
// Install the Jsr/Ret inliner adapter, we have had reports of code still using the
// Jsr/Ret deprecated byte codes.
// see https://code.google.com/p/android/issues/detail?id=220019
return new JSRInlinerAdapter(methodVisitor, access, name, newDesc, signature, exceptions);
}
/**
* For each method in the class being instrumented, <code>visitMethod</code> is called and the
* returned MethodVisitor is used to visit the method. Note that a new MethodVisitor is
* constructed for each method.
*/
@Override
public MethodVisitor visitMethod(
int access, String base, String desc, String signature, String[] exceptions) {
MethodVisitor mv = cv.visitMethod(access, base, desc, signature, exceptions);
if (mv != null) {
// We need to compute stackmaps (see
// AllocationInstrumenter#instrument). This can't really be
// done for old bytecode that contains JSR and RET instructions.
// So, we remove JSRs and RETs.
JSRInlinerAdapter jsria =
new JSRInlinerAdapter(mv, access, base, desc, signature, exceptions);
AllocationMethodAdapter aimv =
new AllocationMethodAdapter(jsria, recorderClass, recorderMethod);
LocalVariablesSorter lvs = new LocalVariablesSorter(access, desc, aimv);
aimv.lvs = lvs;
mv = lvs;
}
return mv;
}
@Override
public MethodVisitor visitMethod(int access, String name, String desc,
String signature, String[] exceptions) {
MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
ModelGeneratorMethodVisitor modelGeneratorMethodVisitor = new ModelGeneratorMethodVisitor(classMap,
inheritanceMap, passthroughDataflow, serializableDecider, api, mv, this.name, access, name, desc, signature, exceptions);
return new JSRInlinerAdapter(modelGeneratorMethodVisitor, access, name, desc, signature, exceptions);
}
@Override
public MethodVisitor visitMethod(int access, String name, String desc,
String signature, String[] exceptions) {
MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
MethodCallDiscoveryMethodVisitor modelGeneratorMethodVisitor = new MethodCallDiscoveryMethodVisitor(
api, mv, this.name, name, desc);
return new JSRInlinerAdapter(modelGeneratorMethodVisitor, access, name, desc, signature, exceptions);
}
static byte[] fixJSRInlining(byte[] byteCode) {
ClassReader reader = new ClassReader(byteCode);
ClassWriter writer = new FixedClassWriter(reader, 0);
ClassVisitor visitor = new ClassVisitor(Opcodes.ASM5, writer) {
@Override public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
return new JSRInlinerAdapter(super.visitMethod(access, name, desc, signature, exceptions), access, name, desc, signature, exceptions);
}
};
reader.accept(visitor, 0);
return writer.toByteArray();
}
@Override
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
BytecodeMethod mtd = new BytecodeMethod(clsName, access, name, desc, signature, exceptions);
cls.addMethod(mtd);
JSRInlinerAdapter a = new JSRInlinerAdapter(new MethodVisitorWrapper(super.visitMethod(access, name, desc, signature, exceptions), mtd), access, name, desc, signature, exceptions);
return a;
}
@Override
public MethodVisitor visitMethod(int access, String name, String descriptor,
@Nullable String signature, String /*@Nullable*/ [] exceptions) {
MethodVisitor mv =
checkNotNull(cv).visitMethod(access, name, descriptor, signature, exceptions);
return new JSRInlinerAdapter(mv, access, name, descriptor, signature, exceptions);
}
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
return new JSRInlinerAdapter(super.visitMethod(access, name, desc, signature, exceptions), access, name, desc, signature, exceptions);
}
/**
* Insert Constructor specific logic({@link ConstructorRedirection} and
* {@link ConstructorBuilder}) 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 = transformAccessForStark(access);
MethodVisitor defaultVisitor = super.visitMethod(access, name, desc, signature, exceptions);
MethodNode method =
checkNotNull(
getMethodByNameInClass(name, desc, classAndInterfaceNode),
"Method found by visitor but not in the pre-parsed class node.");
// does the method use blacklisted APIs.
boolean hasIncompatibleChange = StarkMethodVerifier.verifyMethod(method)
!= StarkVerifierStatus.COMPATIBLE;
if (hasIncompatibleChange
|| disableRedirectionForClass
|| !isAccessCompatibleWithStark(access)) {
return defaultVisitor;
}
if (name.equals(ByteCodeUtils.CLASS_INITIALIZER)) {
classInitializerAdded = true;
return isInterface
? new ISInterfaceStaticInitializerMethodVisitor(
defaultVisitor, access, name, desc)
: defaultVisitor;
}
ArrayList<Type> args = new ArrayList<>(Arrays.asList(Type.getArgumentTypes(desc)));
boolean isStatic = (access & Opcodes.ACC_STATIC) != 0;
if (!isStatic) {
args.add(0, Type.getType(Object.class));
}
// Install the Jsr/Ret inliner adapter, we have had reports of code still using the
// Jsr/Ret deprecated byte codes.
// see https://code.google.com/p/android/issues/detail?id=220019
JSRInlinerAdapter jsrInlinerAdapter =
new JSRInlinerAdapter(defaultVisitor, access, name, desc, signature, exceptions);
ISAbstractMethodVisitor mv =
isInterface
? new ISDefaultMethodVisitor(jsrInlinerAdapter, access, name, desc)
: new ISMethodVisitor(jsrInlinerAdapter, access, name, desc);
if (name.equals(ByteCodeUtils.CONSTRUCTOR)) {
if ((access & Opcodes.ACC_SYNTHETIC) != 0
|| ByteCodeUtils.isAnnotatedWith(method, "Lkotlin/jvm/JvmOverloads;")) {
return defaultVisitor;
}
Constructor constructor = ConstructorBuilder.build(visitedClassName, method);
LabelNode start = 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));
}
mv.addRedirection(new ConstructorRedirection(start, constructor, args));
} else {
mv.addRedirection(
new MethodRedirection(
new LabelNode(mv.getStartLabel()),
name + "." + desc,
args,
Type.getReturnType(desc)));
}
method.accept(mv);
return null;
}
public static MethodNode applyJsrInlineAdapter(MethodNode mn) {
final JSRInlinerAdapter adapter = new JSRInlinerAdapter(mn, mn.access, mn.name, mn.desc, mn.signature, mn.exceptions.toArray(new String[0]));
mn.accept(adapter);
return adapter;
}
@Override
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
MethodVisitor origVisitor = super.visitMethod(access, name, desc, signature, exceptions);
return new JSRInlinerAdapter(origVisitor, access, name, desc, signature, exceptions);
}