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