Why does Android classloader allow reflective access to the public field of a package-private class from another package?
Asked Answered
A

1

10

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.

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:

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.

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

Afterpiece answered 11/10, 2015 at 0:37 Comment(0)
O
2

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

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.

Ordinance answered 18/10, 2015 at 13:28 Comment(1)
Good catch, and the commit code looks indeed like it would reject access to fields of non-public classes in a different package, but although the commit addresses a bug specific to ART and is included from Lollipop on (meaning it should only reproduce on KitKat ART), the sample code in my question does not throw on any Android VM, Dalvik nor (latest) ART. You convinced me it could be a bug though so I submitted an issue to AOSP, we'll see whether it is intentional or not. Thanks.Afterpiece

© 2022 - 2024 — McMap. All rights reserved.