Java类成员访问权限和类加载器的关系?

ningandjin 2014-06-19
Hi All

以前看Java访问权限的时候,就是public ,private, protected,default和private。 public和private比较好理解,就是所有都能访问,和只有自己能访问。

但是对于protected和default来说,就涉及到包的概念了,在虚拟机规范里面对访问权限的描述如下:

“一个类或接口 C 对另外一个类或接口 D 是可见的(Accessible),当且仅当下面的条件之一 成立:
 C 是 public 的。
 C 和 D 处于同一个运行包(Runtime Package,§5.3)下面。 一个字段或方法 R 对另外一个类或接口 D 可见的,当且仅当下面的条件之一成立:
 R 是 public 的。
 R 在 C 中是 protected,那么 D 要么与 C 相同,要么就是 C 的子类。如果 R 不是 static的,那么到 R 的符号引用就必须包含一个到 T 类的符号引用,这里的 T 要么与 D 相同,要么就是 D 的子类或父类。
 R 要么是 protected,要么是默认访问权限(既不是 public,也不是 protected,更
不是 private,并且它所属的那个类应该与 D 处于同一运行包下)。
 R 是 private 的,它声明在 D 类中。 上面的这些对权限控制的讨论忽略了一些限制,就是对于 protected 字段访问或方法调用的
目标(调用的目标必须是 D 或它的子类型)。这需要在验证部分(§5.4.1)做相应地检查。它不 是链接过程中的访问控制所需要涉及的。”


对其中的这一句“ R 要么是 protected,要么是默认访问权限(既不是 public,也不是 protected,更不是 private,并且它所属的那个类应该与 D 处于同一运行包下)。”不是很理解,不知道哪位大大能解答一下?

我个人测试了下,不同类加载器下的同样包名的类之间不能相互访问对方的protected,default成员。
RednaxelaFX 2014-06-20
原文:http://docs.oracle.com/javase/specs/jvms/se8/html/jvms-5.html#jvms-5.4.4

ningandjin 写道
我个人测试了下,不同类加载器下的同样包名的类之间不能相互访问对方的protected,default成员。

其实关键点在于“运行时包”吧。Runtime package由<类加载器, 包全限定名>决定,只要类加载器不一样,包名是否相同都肯定不是在同一个运行时包下。
ningandjin 2014-06-20
RednaxelaFX 写道
原文:http://docs.oracle.com/javase/specs/jvms/se8/html/jvms-5.html#jvms-5.4.4
其实关键点在于“运行时包”吧。Runtime package由<类加载器, 包全限定名>决定,只要类加载器不一样,包名是否相同都肯定不是在同一个运行时包下。


那么,可不可以认为在谈访问权限的时候所指的“包可以访问”都是指的Runtime package?
RednaxelaFX 2014-06-20
ningandjin 写道
RednaxelaFX 写道
原文:http://docs.oracle.com/javase/specs/jvms/se8/html/jvms-5.html#jvms-5.4.4
其实关键点在于“运行时包”吧。Runtime package由<类加载器, 包全限定名>决定,只要类加载器不一样,包名是否相同都肯定不是在同一个运行时包下。


那么,可不可以认为在谈访问权限的时候所指的“包可以访问”都是指的Runtime package?

嗯必须的。这是Java一个比较坑的地方。Java语言规范很多时候只介绍了静态的语义,读者不留心的话可能会忽视它与动态语义的差异。

本来如果一个JVM实例上运行多个应用,每个应用分别只用一个类加载器来加载自己的类,那通常也不会掉这坑里——同应用的类都由同类加载器所加载所以在同一命名空间下,没问题;而不同应用之间本来就不应该能相互访问,通过不同类加载器实现隔离,这很好。

但实际情况是类加载器的设计太灵活了,导致类加载器之间依赖关系复杂,然后就可能掉这坑里了…
Global site tag (gtag.js) - Google Analytics