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.
  • Field Details

    • OBJECT_TYPE

      protected static final org.objectweb.asm.Type OBJECT_TYPE
  • Constructor Details

  • Method Details

    • instrument

      public byte[] instrument(ClassDetails classDetails, InstrumentationConfiguration config, ClassNodeProvider classNodeProvider)
    • instrument

      public void instrument(MutableClass mutableClass)
    • 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 the ClassHandler.
    • 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 instrumented
      method - Method to be instrumented, must be native
    • directMethodName

      protected static String directMethodName(MutableClass mutableClass, String originalName)
    • exceptionArray

      protected String[] exceptionArray(org.objectweb.asm.tree.MethodNode method)
    • 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()
    • setNativeCallHandler

      public void setNativeCallHandler(NativeCallHandler nativeCallHandler)