1 package org.robolectric.internal.bytecode; 2 3 import java.lang.invoke.MethodHandle; 4 import java.lang.invoke.MethodType; 5 6 /** 7 * This interface is used by Robolectric when instrumented classes are created and interacted with. 8 */ 9 public interface ClassHandler { 10 11 /** 12 * Called by Robolectric when an instrumented class is first loaded into a sandbox and is ready to 13 * be statically initialized. 14 * 15 * <p>This happens *in place of* any static initialization that may be performed by the class 16 * being loaded. The class will have a method named {@code __staticInitializer__} which may be 17 * invoked to perform its normal initialization from {@code <clinit>}. 18 * 19 * @param clazz the class being loaded 20 */ classInitializing(Class clazz)21 void classInitializing(Class clazz); 22 23 /** 24 * Called by Robolectric to determine how to create and initialize a shadow object when a new 25 * instance of an instrumented class has been instantiated. (but only on JVMs which support the 26 * {@code invokedynamic} instruction). 27 * 28 * <p>The returned {@link MethodHandle} will be invoked after the new object has been allocated 29 * but before its constructor code is executed. 30 * 31 * <p>Note that this is not directly analogous to {@link #initializing(Object)}; the return value 32 * from this method will be cached and used again for other instantiations of instances of the 33 * same class. 34 * 35 * @param theClass the instrumented class 36 * @return a data value to be associated with the new instance 37 * @see #getShadowCreator(Class) for older JVMs 38 * @see ShadowInvalidator for invalidating the returned {@link MethodHandle} 39 */ getShadowCreator(Class<?> theClass)40 MethodHandle getShadowCreator(Class<?> theClass); 41 42 /** 43 * Called by Robolectric when an instrumented method is invoked. 44 * 45 * <p>Implementations should return an {@link MethodHandle}, which will be invoked with details 46 * about the current instance and parameters. 47 * 48 * <p>Implementations may also return null, in which case the method's original code will be 49 * executed. 50 * 51 * @param theClass the class on which the method is declared 52 * @param name the name of the method 53 * @param methodType the method type 54 * @param isStatic true if the method is static 55 * @return a method handle to invoke, or null if the original method's code should be executed 56 * @see ShadowInvalidator for invalidating the returned {@link MethodHandle} 57 */ findShadowMethodHandle( Class<?> theClass, String name, MethodType methodType, boolean isStatic, boolean isNative)58 MethodHandle findShadowMethodHandle( 59 Class<?> theClass, String name, MethodType methodType, boolean isStatic, boolean isNative) 60 throws IllegalAccessException; 61 62 /** 63 * Called by Robolectric when an intercepted method is invoked. 64 * 65 * <p>Unlike instrumented methods, calls to intercepted methods are modified in place by 66 * Robolectric in the calling code. This is useful when the method about to be invoked doesn't 67 * exist in the current JVM (e.g. because of Android differences). 68 * 69 * @param signature the JVM internal-format signature of the method being invoked (e.g. {@code 70 * android/view/View/measure(II)V}) 71 * @param instance the instance on which the method would have been invoked 72 * @param params the parameters to the method 73 * @param theClass the class on which the method is declared 74 * @return the value to be returned 75 * @throws Throwable if anything bad happens 76 */ intercept(String signature, Object instance, Object[] params, Class<?> theClass)77 Object intercept(String signature, Object instance, Object[] params, Class<?> theClass) 78 throws Throwable; 79 80 /** 81 * Removes Robolectric noise from stack traces. 82 * 83 * @param throwable the exception to be stripped 84 * @param <T> the type of exception 85 * @return the stripped stack trace 86 */ stripStackTrace(T throwable)87 <T extends Throwable> T stripStackTrace(T throwable); 88 } 89