-
Notifications
You must be signed in to change notification settings - Fork 1.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support customized implementation method name #8841
Support customized implementation method name #8841
Conversation
9317483
to
a3d77b2
Compare
@hoisie @brettchabot It's a prototype, but it's ready for reviewing now. |
a3d77b2
to
5e72a06
Compare
5e72a06
to
f8ef8d2
Compare
Friendly ping @hoisie @brettchabot, PTAL. |
sandbox/src/main/java/org/robolectric/internal/bytecode/ShadowWrangler.java
Outdated
Show resolved
Hide resolved
@utzcoz it looks like https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/java/lang/Class.java#L2905 @CallerSensitive
public Method getDeclaredMethod(String name, Class<?>... parameterTypes)
throws NoSuchMethodException, SecurityException {
Objects.requireNonNull(name);
@SuppressWarnings("removal")
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkMemberAccess(sm, Member.DECLARED, Reflection.getCallerClass(), true);
}
Method method = searchMethods(privateGetDeclaredMethods(false), name, parameterTypes);
if (method == null) {
throw new NoSuchMethodException(methodToString(name, parameterTypes));
}
return getReflectionFactory().copyMethod(method);
} This is searchMethods: // This method does not copy the returned Method object!
private static Method searchMethods(Method[] methods,
String name,
Class<?>[] parameterTypes)
{
ReflectionFactory fact = getReflectionFactory();
Method res = null;
for (Method m : methods) {
if (m.getName().equals(name)
&& arrayContentsEq(parameterTypes,
fact.getExecutableSharedParameterTypes(m))
&& (res == null
|| (res.getReturnType() != m.getReturnType()
&& res.getReturnType().isAssignableFrom(m.getReturnType()))))
res = m;
}
return res;
} |
Looks like the only difference is that calling getDeclaredMethods calls @CallerSensitive
public Method[] getDeclaredMethods() throws SecurityException {
@SuppressWarnings("removal")
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkMemberAccess(sm, Member.DECLARED, Reflection.getCallerClass(), true);
}
return copyMethods(privateGetDeclaredMethods(false));
} |
@hoisie If |
…hods Previously, in ShadowWrangler, shadow method lookup was performed using ShadowClass.findDeclaredMethod. It was called once to look for an exact match of a shadow method, and sometimes called again to check for a looseSignatures match. There are plans to add new features and capabilities to the way that shadow methods are matched. For example: * looseSignatures being replaced with a more minimal @classname("internal.type") annotation. * If the signature of a method changes across SDK levels, we could introduce different method names that map to the same method name. However, to search for methods that cannot be matched using ShadowClass.findDeclaredMethod, it is required to iterate over all candidate methods using ShadowClass.findDeclaredMethods. There were some questions about the performance of using ShadowClass.findDeclaredMethods + iteration. However, after some preliminary benchmarks, this approach is surprisingly approximately 25% faster than using ShadowClass.findDeclaredMethod. It is perhaps due to the internal caching of ShadowClass.findDeclaredMethods. With this change, it will be possible to perform more advanced filtering and searching for methods. For #8841 PiperOrigin-RevId: 619288002
…hods Previously, in ShadowWrangler, shadow method lookup was performed using ShadowClass.findDeclaredMethod. It was called once to look for an exact match of a shadow method, and sometimes called again to check for a looseSignatures match. There are plans to add new features and capabilities to the way that shadow methods are matched. For example: * looseSignatures being replaced with a more minimal @classname("internal.type") annotation. * If the signature of a method changes across SDK levels, we could introduce different method names that map to the same method name. However, to search for methods that cannot be matched using ShadowClass.findDeclaredMethod, it is required to iterate over all candidate methods using ShadowClass.findDeclaredMethods. There were some questions about the performance of using ShadowClass.findDeclaredMethods + iteration. However, after some preliminary benchmarks, this approach is surprisingly approximately 25% faster than using ShadowClass.findDeclaredMethod. It is perhaps due to the internal caching of ShadowClass.findDeclaredMethods. With this change, it will be possible to perform more advanced filtering and searching for methods. For #8841 PiperOrigin-RevId: 619979740
d3d3ebe
to
57d5b24
Compare
Interesting. I keep to use From my experience, I can't use only one iteration to finish all types of finding jobs, as the exact matching has the first and highest priority than other approaches. So I reused the origin iteration with the exact method matching with highest priority and then looseSignature, and adding a new iteration for |
57d5b24
to
719bf7e
Compare
@hoisie Friendly ping for reviewing. I want to land it before other contributors start to code for GSoC. |
719bf7e
to
039de38
Compare
@hoisie Maybe we can discuss this one? |
1. Expand Implementation with a new method called methodName for mapped method name. 2. Expand SdkStore to consider mapped shadow method for validation. 3. Expand shadow method finding logic when running to add mapped shadow method finding logic as the third priority after looseSignature. 4. Split `ShadowBluetoothAdapter#setScanMode` into two methods for different SDKs to test mapped shadow method. Signed-off-by: utzcoz <utzcoz@outlook.com>
039de38
to
849e1bc
Compare
Friendly ping @hoisie for reviewing. |
I think developers can use JvmName to set the generated method signature, especially method name for internal Kotlin property's setter and getter. |
@hoisie @MGaetan89 Okay, I decide to land it because long-time no-feedback. If you have other questions, please let me know, I can send new PRs to fix them or @Mia0451 can help to improve it under her GSoC project as methodName is very important to remove looseSignature for classes that have same method name + different signatures for different Android SDKs. |
… into google branch. The original commit was by utzcoz. google has custom instrumentation that needs special handling of custom method names that needs to be done before the open source main branch can get merged with google branch. This dupe commit will be removed during the next `google` -> `master` merge. See #8841 PiperOrigin-RevId: 643114647
… into google branch. The original commit was by utzcoz. google has custom instrumentation that needs special handling of custom method names that needs to be done before the open source main branch can get merged with google branch. This dupe commit will be removed during the next `google` -> `master` merge. See #8841 PiperOrigin-RevId: 643448518
Sometimes internal methods return different types for different SDKs. It's safe because
these methods are internal/private methods, not public methods. To support different return
types of a method for different SDKs, we often use looseSignature method, although all return
types are common types like bool and int. This field/property can be used to fix this issue by
using different real methods for different SDKs.