为什么Android classloader允许从另一个包返回包私有类的公共字段?

时间:2021-04-16 20:53:11

It seems that the Android application class loader allows to reflectively acquire a reference to the public static field of a package-private class even from a different package (than the one the aforementioned class is defined in), while Sun JDK classloader for example doesn't.

似乎Android应用程序类装入器允许从不同的包(与前面的类定义的包不同)获得对包私有类公共静态字段的引用,而Sun JDK类装入器则不允许。

More concretely, given the following class definition:

更具体地说,给定以下类定义:

package org.example.a

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

And the following code in a separate package:

并将以下代码单独打包:

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)
    }
}

When executed on Sun JVM it throws an IllegalAccessException on the last line:

当在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)
...

However, when run on an Android device (5.1 Lollipop FWIW) it executes without throwing and creatorFieldRef.get(null) actually returns a valid reference to the CREATOR field.

但是,当在Android设备上运行时(5.1 Lollipop FWIW),它不需要抛出和creatorFieldRef.get(null),实际上返回一个对创建者字段的有效引用。

My question is : why is it the case ? Is it a bug or a feature of the Android classloader ?? (or, if applicable, what did I get wrong in my example ?)

我的问题是:为什么会这样?它是Android类加载器的一个bug还是一个特性?(或者,如果适用的话,在我的示例中哪里出错了?)

1 个解决方案

#1


2  

Seems that it is a bug in the android runtime which was fixed in this commit:

这似乎是android运行时的一个缺陷,它是固定在这个提交上的:

Add access checks to Method and Field reflection.

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

Prior to this commit it was possible to access fields via reflection in an unrestricted way or even set the value of final fields.

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

The access check is now implemented in the runtime functions ValidateFieldAccess and ValidateAccess.

访问检查现在在运行时函数ValidateFieldAccess和ValidateAccess中实现。

#1


2  

Seems that it is a bug in the android runtime which was fixed in this commit:

这似乎是android运行时的一个缺陷,它是固定在这个提交上的:

Add access checks to Method and Field reflection.

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

Prior to this commit it was possible to access fields via reflection in an unrestricted way or even set the value of final fields.

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

The access check is now implemented in the runtime functions ValidateFieldAccess and ValidateAccess.

访问检查现在在运行时函数ValidateFieldAccess和ValidateAccess中实现。