java类的访问权限问题

  Android中java类的访问权限控制在art中的Class::CanAccessMember实现。其中,参数access_to是要访问的属性或者方法所在的类,member_flags是要访问的属性或者方法的flag(Android提供public、protected、private修饰符来设置flag)。规则如下(以下规则优先级从高到低):
  1.如果要访问的内容在当前类中,允许访问;
  2.如果要访问的内容设置了public修饰符,允许访问;
  3.如果要访问的内容设置了private修饰符,不允许访问;
  4.如果要访问的内容设置了protected修饰符,当前类不是接口且是要访问的内容所在类的子类,允许访问;
  5.通过Class::IsInSamePackage进行判定,该函数返回true表示允许访问。

art/runtime/mirror/class-inl.h

inline bool Class::CanAccessMember(ObjPtr<Class> access_to, uint32_t member_flags) {
  // Classes can access all of their own members
  if (this == access_to) {//1.
    return true;
  }
  // Public members are trivially accessible
  if (member_flags & kAccPublic) {//2.
    return true;
  }
  // Private members are trivially not accessible
  if (member_flags & kAccPrivate) {//3.
    return false;
  }
  // Check for protected access from a sub-class, which may or may not be in the same package.
  if (member_flags & kAccProtected) {//4.
    if (!this->IsInterface() && this->IsSubClass(access_to)) {
      return true;
    }
  }
  // Allow protected access from other classes in the same package.
  return this->IsInSamePackage(access_to);//5.
}

  Class::IsInSamePackage接收一个参数that,该参数是要访问的内容所在的类。
  1.当前类和参数类是同一个类时,返回true;
  2.当前类和参数类绑定的不是同一个classloader时,返回false;
  3.如果当前类或参数类是数组类型,则将它们的基本类型类进行比较(例如java.lang.String[]的基本类型类是java.lang.String),如果它们的基本类型类是同一个类,返回true。
  4.如果当前类和参数类在同一个包里,返回true。判断同一个包的规则是找到它们在art里面的限定类名(例如Ljava/lang/invoke/MethodHandle和Ljava/lang/invoke/CallSite),从头开始找到它们的最大相同子串的下标(最大子串为Ljava/lang/invoke/),如果两个类从该下标开始都没有出现’/’,可以视作是在同一个包(java/lang/invoke/后面分别是MethodHandle和CallSite,没有出现’/’,所以是在同一个包)。

art/runtime/mirror/class.cc

bool Class::IsInSamePackage(ObjPtr<Class> that) {
  ObjPtr<Class> klass1 = this;
  ObjPtr<Class> klass2 = that;
  if (klass1 == klass2) {//1.
    return true;
  }
  // Class loaders must match.
  if (klass1->GetClassLoader() != klass2->GetClassLoader()) {//2.
    return false;
  }
  // Arrays are in the same package when their element classes are.
  while (klass1->IsArrayClass()) {
    klass1 = klass1->GetComponentType();
  }
  while (klass2->IsArrayClass()) {
    klass2 = klass2->GetComponentType();
  }
  // trivial check again for array types
  if (klass1 == klass2) {//3.
    return true;
  }
  // Compare the package part of the descriptor string.
  std::string temp1, temp2;
  return IsInSamePackage(klass1->GetDescriptor(&temp1), klass2->GetDescriptor(&temp2));//4.
}

art/runtime/mirror/class.cc

bool Class::IsInSamePackage(std::string_view descriptor1, std::string_view descriptor2) {
  size_t i = 0;
  size_t min_length = std::min(descriptor1.size(), descriptor2.size());
  while (i < min_length && descriptor1[i] == descriptor2[i]) {
    ++i;
  }
  if (descriptor1.find('/', i) != std::string_view::npos ||
      descriptor2.find('/', i) != std::string_view::npos) {
    return false;
  } else {
    return true;
  }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Invoker123

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值