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 运行时中的错误:

添加对方法和字段反射的访问检查。

在此提交之前,可以通过反射以不受限制的方式访问字段,甚至可以设置最终字段的值

访问检查现在在运行时函数ValidateFieldAccessValidateAccess.

于 2015-10-18T13:28:08.823 回答