简体   繁体   中英

Java Reflection on Android Studio unable to find public static method to invoke

The Java reflection code in my Android application invokes a public static method in a package B, from a package A.

Recently, after some Gradle upgrades, I am unable to invoke the same method. My implementation fails with a NoSuchMethodFound exception. How can I get the implementation to be able to find this method?

I've tried printing all the available methods from the class. The result is all public non-static methods. No static methods are available to be invoked. The method I want to invoke is a static "getInstance" method which initializes the class and returns a singleton instance.

Calling Code:

implementationClass = Class.forName(CLIENT_CLASS_NAME, false, ClientProvider.class.getClassLoader());
final Method method = implementationClass.getMethod("getInstance", (Class[]) null);
result = method.invoke(null, (Object[]) null);

Called Code:

/**
* Public static method to be reflected.
*/
public static ClientImpl getInstance() {
    return ClientImplHolder.INSTANCE;
}

/**
 * Private class used to hold the lazily initialized singleton instance.
 */
private static class ClientImplHolder {
    private static final ClientImpl INSTANCE = new ClientImpl();
}

When attempting to 'getMethod', I receive a NoSuchMethodException.

Not sure what I am doing wrong here, appreciate any help. Thanks!

If i understood correctly, you used reflection API wrong

just try this.

public class Test {

    public static void main(String[] args) {
        try {
            ClientImpl client = (ClientImpl) Class.forName(ClientImpl.class.getCanonicalName())
                    .getMethod("getInstance")
                    .invoke(null);

            System.out.println(client.toString() + " with some -> " + client.getSome());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

/**
 * Public static method to be reflected.
 */

class ClientImpl {

    private final int some;

    public int getSome() {
        return some;
    }

    private ClientImpl(int some) {
        this.some = some;
    }

    public static ClientImpl getInstance() {
        return ClientImplHolder.INSTANCE;
    }

    /**
     * Private class used to hold the lazily initialized singleton instance.
     */
    private static class ClientImplHolder {
        private static final ClientImpl INSTANCE = new ClientImpl(123);
    }
}

and it will put correctly result

ClientImpl@<hashcode> with some -> 123

When you use static methods in reflection API, you don't need to call it ClassLoader explicitly, you have to put it's canonicalName in argument, then you can call it's methods.

Try to replace it,maybe it's a parameter problem.

    final Method method = implementationClass.getMethod("getInstance");
    result = method.invoke(null);

Starting in Android 9 (API level 28), the platform restricts which non-SDK interfaces your app can use. These restrictions apply whenever an app references a non-SDK interface or attempts to obtain its handle using reflection.

Turns out Proguard was removing the method from the build since it was not being used elsewhere. Added an exception for the class and the issue went away.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM