似乎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类加载器的错误还是功能? (或者,如果适用的话,我的例子中出了什么问题?)
答案 0 :(得分:2)
似乎这是Android运行时中的一个错误,已在此commit中修复:
为方法和字段反射添加访问检查。
在此提交之前,可以通过不受限制的方式通过反射访问字段,甚至可以设置the value of final fields。
在运行时函数ValidateFieldAccess
和ValidateAccess
中实现了now访问权检查。