Class ClassInstrumentor
java.lang.Object
org.robolectric.internal.bytecode.ClassInstrumentor
- Direct Known Subclasses:
InvokeDynamicClassInstrumentor
public class ClassInstrumentor extends Object
Instruments (i.e. modifies the bytecode) of classes to place the scaffolding necessary to use
Robolectric's shadows.
-
Nested Class Summary
Nested Classes Modifier and Type Class Description static interface
ClassInstrumentor.Decorator
-
Field Summary
Fields Modifier and Type Field Description protected static org.objectweb.asm.Type
OBJECT_TYPE
-
Constructor Summary
Constructors Modifier Constructor Description ClassInstrumentor()
protected
ClassInstrumentor(ClassInstrumentor.Decorator decorator)
-
Method Summary
Modifier and Type Method Description protected void
addCallToRoboInit(MutableClass mutableClass, org.objectweb.asm.tree.MethodNode ctor)
Adds a call $$robo$init, which instantiates a shadow object if required.protected static String
directMethodName(MutableClass mutableClass, String originalName)
protected String[]
exceptionArray(org.objectweb.asm.tree.MethodNode method)
protected void
generateClassHandlerCall(MutableClass mutableClass, org.objectweb.asm.tree.MethodNode originalMethod, String originalMethodName, RobolectricGeneratorAdapter generator)
protected int
getAndroidJarSDKVersion()
byte[]
instrument(ClassDetails classDetails, InstrumentationConfiguration config, ClassNodeProvider classNodeProvider)
void
instrument(MutableClass mutableClass)
protected void
instrumentConstructor(MutableClass mutableClass, org.objectweb.asm.tree.MethodNode method)
Constructors are instrumented as follows: The original constructor will be stripped of its instructions leading up to, and including, the call to super() or this().protected void
instrumentNativeMethod(MutableClass mutableClass, org.objectweb.asm.tree.MethodNode method)
Creates native stub which returns the default return value.protected void
instrumentNormalMethod(MutableClass mutableClass, org.objectweb.asm.tree.MethodNode method)
Instruments a normal method Rename the method frommethodName
to$$robo$$methodName
.protected void
interceptInvokeVirtualMethod(MutableClass mutableClass, ListIterator<org.objectweb.asm.tree.AbstractInsnNode> instructions, org.objectweb.asm.tree.MethodInsnNode targetMethod)
Decides to call through the appropriate method to intercept the method with an INVOKEVIRTUAL Opcode, depending if the invokedynamic bytecode instruction is available (Java 7+).protected void
makeMethodPrivate(org.objectweb.asm.tree.MethodNode method)
Replaces protected and public class modifiers with private.void
setAndroidJarSDKVersion(int androidJarSDKVersion)
protected void
writeCallToInitializing(MutableClass mutableClass, RobolectricGeneratorAdapter generator)
-
Field Details
-
OBJECT_TYPE
protected static final org.objectweb.asm.Type OBJECT_TYPE
-
-
Constructor Details
-
ClassInstrumentor
public ClassInstrumentor() -
ClassInstrumentor
-
-
Method Details
-
instrument
public byte[] instrument(ClassDetails classDetails, InstrumentationConfiguration config, ClassNodeProvider classNodeProvider) -
instrument
-
addCallToRoboInit
protected void addCallToRoboInit(MutableClass mutableClass, org.objectweb.asm.tree.MethodNode ctor)Adds a call $$robo$init, which instantiates a shadow object if required. This is to support custom shadows for Jacoco-instrumented classes (except cnstructor shadows). -
writeCallToInitializing
protected void writeCallToInitializing(MutableClass mutableClass, RobolectricGeneratorAdapter generator) -
instrumentConstructor
protected void instrumentConstructor(MutableClass mutableClass, org.objectweb.asm.tree.MethodNode method)Constructors are instrumented as follows:- The original constructor will be stripped of its instructions leading up to, and including, the call to super() or this(). It is also renamed to $$robo$$__constructor__
- A method called __constructor__ is created and its job is to call $$robo$$__constructor__. The __constructor__ method is what gets shadowed if a Shadow wants to shadow a constructor.
- A new constructor is created and contains the stripped instructions of the original constructor leading up to, and including, the call to super() or this(). Then, it has a call to $$robo$init to initialize the Class' Shadow Object. Then, it uses invokedynamic to call __constructor__. Finally, it contains any instructions that might occur after the return statement in the original constructor.
- Parameters:
method
- the constructor to instrument
-
instrumentNormalMethod
protected void instrumentNormalMethod(MutableClass mutableClass, org.objectweb.asm.tree.MethodNode method)Instruments a normal method- Rename the method from
methodName
to$$robo$$methodName
. - Make it private so we can invoke it directly without subclass overrides taking precedence.
- Remove
final
modifiers, if present. - Create a delegator method named
methodName
which delegates to theClassHandler
.
- Rename the method from
-
instrumentNativeMethod
protected void instrumentNativeMethod(MutableClass mutableClass, org.objectweb.asm.tree.MethodNode method)Creates native stub which returns the default return value.- Parameters:
mutableClass
- Class to be instrumentedmethod
- Method to be instrumented, must be native
-
directMethodName
-
exceptionArray
-
interceptInvokeVirtualMethod
protected void interceptInvokeVirtualMethod(MutableClass mutableClass, ListIterator<org.objectweb.asm.tree.AbstractInsnNode> instructions, org.objectweb.asm.tree.MethodInsnNode targetMethod)Decides to call through the appropriate method to intercept the method with an INVOKEVIRTUAL Opcode, depending if the invokedynamic bytecode instruction is available (Java 7+). -
makeMethodPrivate
protected void makeMethodPrivate(org.objectweb.asm.tree.MethodNode method)Replaces protected and public class modifiers with private. -
generateClassHandlerCall
protected void generateClassHandlerCall(MutableClass mutableClass, org.objectweb.asm.tree.MethodNode originalMethod, String originalMethodName, RobolectricGeneratorAdapter generator) -
setAndroidJarSDKVersion
public void setAndroidJarSDKVersion(int androidJarSDKVersion) -
getAndroidJarSDKVersion
protected int getAndroidJarSDKVersion()
-