Похоже, что загрузчик классов приложений Android позволяет рефлексивно получить ссылку на поле public static
класса private-private даже из другого пакета (чем тот, который указан выше в этом классе), в то время как загрузчик классов Java 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? (или, если применимо, что я ошибся в моем примере?)