I'm working on command line tool for Android (think of am), trying to utilize the power of ByteBuddy to stub the static method getApplicationContext defined in android.security.KeyStore
However - the method seem to be invisible to ByteBuddy getDeclaredMethods when subclassing the android.security.KeyStore and hence it is unable to intercept it.
When using getMethods from the reflection API i'm able to list the method.
Class AndroidKeyStore = Class.forName("android.security.KeyStore");
Method[] keyStoreMethods = new ByteBuddy()
.with(TypeValidation.DISABLED)
.subclass(AndroidKeyStore, ConstructorStrategy.Default.IMITATE_SUPER_CLASS)
.name("KeyStoreMasker")
.method(ElementMatchers.named("getApplicationContext"))
.intercept(SuperMethodCall.INSTANCE)
.make()
.load(getClass().getClassLoader(),
new AndroidClassLoadingStrategy
.Injecting(new File("/data/app/cmdutil")))
.getLoaded()
.getDeclaredMethods();
for(i = 0; i < keyStoreMethods .length; i++) {
System.out.println("method = " + keyStoreMethods[i].toString());
}
When running the above, I was expecting to have a single method - getApplicationContext in the subclass. However the subclass doesn't contain any methods.
Replacing the call to getDeclaredMethods by getMethods I'm able to list all public method of the superclass.
By replacing the intercepted method to a non-static one (for example "state"), i'm able to list the method using ByteBuddy's getDeclaredMethods function:
Number of declared methods in keyStoreMethods: 2
method = public android.security.KeyStore$State AndroidKeyStoreMasker.state()
method = public android.security.KeyStore$State AndroidKeyStoreMasker.state(int)
So my final conclusion is that ByteBuddy (or my usage case with ByteBuddy) has some issue with static method visibility.
Reference to android.security.KeyStore.java: https://android.googlesource.com/platform/frameworks/base/+/master/keystore/java/android/security/KeyStore.java
Any help would be much appreaciated.