10

Android アプリケーション クラス ローダーは、public static(前述のクラスが定義されているものとは異なる) 別のパッケージからでもパッケージ プライベート クラスのフィールドへの参照を反射的に取得できるようですが、たとえば Sun JDK クラスローダーはそうではありません。

より具体的には、次のクラス定義が与えられます。

package org.example.a

class PackagePrivateClass {
    public static final Parcelable.Creator<PackagePrivateClass> CREATOR = generateCreator();
}

そして、別のパッケージの次のコード:

package org.example.b

public class TestClass {
    public void testMethod() {
        final Class classRef = Class.forName("org.example.a.PackagePrivateClass");
        final Field creatorFieldRef = classRef.getField("CREATOR");
        creatorFieldRef.get(null);  // throws here (unless on Android)
    }
}

Sun JVM で実行するIllegalAccessExceptionと、最後の行で次のようにスローされます。

java.lang.IllegalAccessException: Class org.example.b.TestClass can not access a member of class org.example.a.PackagePrivateClass with modifiers "public static final"
at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:102)
...

ただし、Android デバイス (5.1 Lollipop FWIW) で実行すると、スローせずに実行され、creatorFieldRef.get(null)実際にはフィールドへの有効な参照が返されCREATORます。

私の質問は次のとおりです。なぜそうなのですか?Androidクラスローダーのバグか機能ですか?? (または、該当する場合、私の例で何が間違っていましたか?)

4

1 に答える 1

2

このコミットで修正されたのは Android ランタイムのバグのようです:

メソッドとフィールドのリフレクションにアクセス チェックを追加します。

このコミットの前は、リフレクションを介して制限のない方法でフィールドにアクセスしたり、 final フィールドの値を設定することさえ可能でした。

アクセス チェックが実行時関数およびに実装されるようになりました。ValidateFieldAccessValidateAccess

于 2015-10-18T13:28:08.823 に答える