byte-buddy icon indicating copy to clipboard operation
byte-buddy copied to clipboard

Android sun.reflect.ReflectionFactory no found

Open anonyein opened this issue 1 year ago • 4 comments

@Super(strategy = Super.Instantiation.UNSAFE, proxyType = TargetType.class) could not fit Android and how to get super object. Starting with Android 26 (Oreo, 8.0), Google began to gradually remove access to the internal sun class for reflection because it could cause security and compatibility issues.

anonyein avatar Oct 20 '24 14:10 anonyein

That is why this approach is discouraged. Rather use the method as a basis and inject a method handle, for example. What are you trying to achieve? Do you need to invoke any method?

raphw avatar Oct 20 '24 20:10 raphw

That is why this approach is discouraged. Rather use the method as a basis and inject a method handle, for example. What are you trying to achieve? Do you need to invoke any method?

@raphw yes, need to invoke any method https://github.com/caoccao/JavetBuddy/blob/main/src/main/java/com/caoccao/javet/buddy/interop/proxy/BaseDynamicObjectHandler.java#L101 https://github.com/caoccao/JavetBuddy/blob/main/src/main/java/com/caoccao/javet/buddy/interop/proxy/DynamicObjectExtendHandler.java#L87

I want to make "intercept" method fit for Android

anonyein avatar Oct 21 '24 00:10 anonyein

In this case you might be able to use Super.Instantiation.CONSTRUCTOR? As long as the constructor does not do any method calls on the supplied objects, or any other input checks, this will work.

raphw avatar Oct 21 '24 06:10 raphw

In this case you might be able to use Super.Instantiation.CONSTRUCTOR? As long as the constructor does not do any method calls on the supplied objects, or any other input checks, this will work.

  W  java.lang.IllegalStateException: size = 0
2024-10-21 18:28:17.548  9157-19242 System.err                                   W  	at net.bytebuddy.matcher.FilterableList$AbstractBase.getOnly(FilterableList.java:139)
2024-10-21 18:28:17.550  9157-19242 System.err                                   W  	at net.bytebuddy.implementation.auxiliary.TypeProxy$ForSuperMethodByConstructor.apply(TypeProxy.java:458)
2024-10-21 18:28:17.551  9157-19242 System.err                                   W  	at net.bytebuddy.implementation.bind.MethodDelegationBinder$ParameterBinding$Anonymous.apply(MethodDelegationBinder.java:258)
2024-10-21 18:28:17.551  9157-19242 System.err                                   W  	at net.bytebuddy.implementation.bytecode.StackManipulation$Compound.apply(StackManipulation.java:243)
2024-10-21 18:28:17.552  9157-19242 System.err                                   W  	at net.bytebuddy.implementation.bind.MethodDelegationBinder$MethodBinding$Builder$Build.apply(MethodDelegationBinder.java:564)
2024-10-21 18:28:17.552  9157-19242 System.err                                   W  	at net.bytebuddy.implementation.bytecode.StackManipulation$Compound.apply(StackManipulation.java:243)
2024-10-21 18:28:17.553  9157-19242 System.err                                   W  	at net.bytebuddy.implementation.MethodDelegation$Appender.apply(MethodDelegation.java:1350)
2024-10-21 18:28:17.553  9157-19242 System.err                                   W  	at net.bytebuddy.dynamic.scaffold.TypeWriter$MethodPool$Record$ForDefinedMethod$WithBody.applyCode(TypeWriter.java:732)
2024-10-21 18:28:17.554  9157-19242 System.err                                   W  	at net.bytebuddy.dynamic.scaffold.TypeWriter$MethodPool$Record$ForDefinedMethod$WithBody.applyBody(TypeWriter.java:717)
2024-10-21 18:28:17.554  9157-19242 System.err                                   W  	at net.bytebuddy.dynamic.scaffold.TypeWriter$MethodPool$Record$ForDefinedMethod.apply(TypeWriter.java:624)
2024-10-21 18:28:17.555  9157-19242 System.err                                   W  	at net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ForCreation.create(TypeWriter.java:6077)
2024-10-21 18:28:17.555  9157-19242 System.err                                   W  	at net.bytebuddy.dynamic.scaffold.TypeWriter$Default.make(TypeWriter.java:2246)
2024-10-21 18:28:17.555  9157-19242 System.err                                   W  	at net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase$UsingTypeWriter.make(DynamicType.java:4057)
2024-10-21 18:28:17.556  9157-19242 System.err                                   W  	at net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase.make(DynamicType.java:3741)
2024-10-21 18:28:17.556  9157-19242 System.err                                   W  	at net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase$Delegator.make(DynamicType.java:3993)
2024-10-21 18:28:17.557  9157-19242 System.err                                   W  	at com.caoccao.javet.buddy.interop.proxy.BaseDynamicObjectAndroidHandler.getObjectClass(BaseDynamicObjectAndroidHandler.java:138)
2024-10-21 18:28:17.557  9157-19242 System.err                                   W  	at com.caoccao.javet.buddy.interop.proxy.JavetReflectionObjectAndroidFactory.extend(JavetReflectionObjectAndroidFactory.java:103)
    protected static final AndroidClassLoadingStrategy ANDROID_CLASS_LOADING_STRATEGY;

    static {
        File file = new File(JavetOSUtils.TEMP_DIRECTORY, RandomString.make());
        if (!file.exists() && !file.isDirectory()) {
            file.mkdirs();
        }
        ANDROID_CLASS_LOADING_STRATEGY = new AndroidClassLoadingStrategy.Wrapping(file);
    }
    protected Class<T> getObjectClass() {
        DynamicType.Builder<T> builder = new ByteBuddy().subclass(type, CONSTRUCTOR_STRATEGY);
        if (!AutoCloseable.class.isAssignableFrom(type)) {
            builder = builder.implement(AutoCloseable.class);
        }
        try (DynamicType.Unloaded<T> unloadedType = builder
                .method(ElementMatchers.isPublic())
                .intercept(MethodDelegation.to(this))
                .make()) {
            return (Class<T>) unloadedType.load(getClass().getClassLoader(), ANDROID_CLASS_LOADING_STRATEGY).getLoaded();
        }
    }

anonyein avatar Oct 21 '24 10:10 anonyein

You need to set the constructorParameters property on the @Super annotation for this. This property is needed to identify the constructor that you want to call. It needs to resemble the constructor parameter types of the relevant constructor.

raphw avatar Oct 21 '24 12:10 raphw

You need to set the constructorParameters property on the @Super annotation for this. This property is needed to identify the constructor that you want to call. It needs to resemble the constructor parameter types of the relevant constructor.

annotation cannot be variable, constructorParameters cannot be set. Are there other way to get super object?

anonyein avatar Oct 22 '24 00:10 anonyein

That is right, but the proxy type cannot be variable either. What type do you use before @Super?

raphw avatar Oct 22 '24 11:10 raphw

That is right, but the proxy type cannot be variable either. What type do you use before @Super?

https://github.com/caoccao/JavetBuddy/blob/main/src/main/java/com/caoccao/javet/buddy/interop/proxy/DynamicObjectExtendHandler.java#L72 proxyType = TargetType.class

anonyein avatar Oct 22 '24 12:10 anonyein

I see. I will have to add a dynamic resolver for this. That is not much work, so I can add it to the next version.

raphw avatar Oct 22 '24 13:10 raphw

I see. I will have to add a dynamic resolver for this. That is not much work, so I can add it to the next version.

Thank you for your contribution and effort!

anonyein avatar Oct 22 '24 14:10 anonyein

You can now specifiy a constructorResolver property on the annotation to resolve the annotation dynamically.

raphw avatar Oct 22 '24 18:10 raphw

java.lang.IllegalStateException: Cannot invoke Android dex file translation method
at net.bytebuddy.android.AndroidClassLoadingStrategy$DexProcessor$ForSdkCompiler$Dispatcher$ForApi26LevelCompatibleVm.translate(AndroidClassLoadingStrategy.java:647)
at net.bytebuddy.android.AndroidClassLoadingStrategy$DexProcessor$ForSdkCompiler$Conversion.register(AndroidClassLoadingStrategy.java:458)
at net.bytebuddy.android.AndroidClassLoadingStrategy.load(AndroidClassLoadingStrategy.java:164)
at net.bytebuddy.dynamic.TypeResolutionStrategy$Passive.initialize(TypeResolutionStrategy.java:101)
at net.bytebuddy.dynamic.DynamicType$Default$Unloaded.load(DynamicType.java:6367)
    protected static final File Temp_Dir = getCurrentContext().getDir("libs", Context.MODE_PRIVATE);
    protected static final AndroidClassLoadingStrategy ANDROID_CLASS_LOADING_STRATEGY = Temp_Dir.exists() && Temp_Dir.isDirectory() ?
            new AndroidClassLoadingStrategy.Wrapping(Temp_Dir) :
            Temp_Dir.mkdirs() ? new AndroidClassLoadingStrategy.Wrapping(Temp_Dir) : null;
        DynamicType.Builder<T> builder = new ByteBuddy().subclass(type, CONSTRUCTOR_STRATEGY);
        if (!AutoCloseable.class.isAssignableFrom(type)) {
            builder = builder.implement(AutoCloseable.class);
        }
        try (DynamicType.Unloaded<T> unloadedType = builder
                .method(ElementMatchers.isPublic())
                .intercept(MethodDelegation.to(this))
                .make()) {
            return (Class<T>) unloadedType.load(getClass().getClassLoader(), ANDROID_CLASS_LOADING_STRATEGY).getLoaded();
        }

The jar seems cannot be writen into "app_libs/" and only create "app_libs/oat/2QpqXOOB.jar.cur.prof" of 0KB on Android 11

Logcat:

2024-10-23 20:43:33.951  1378-2463  installd                installd                             D  Processing secondary dex path /data/user/0/com.xxxx.xxxx/app_libs/2QpqXOOB.jar
2024-10-23 20:43:33.952  1378-2463  installd                installd                             D  Processed secondary dex file /data/user/0/com.xxxx.xxxx/app_libs/2QpqXOOB.jar result=205
2024-10-23 20:43:33.953  5273-5405  OPDOM                   system_server                        D  performDexOpt secondaryDex end for /data/user/0/com.xxxx.xxxx/app_libs/2QpqXOOB.jar sucessed: true

https://github.com/raphw/byte-buddy/issues/1722

anonyein avatar Oct 23 '24 12:10 anonyein