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实例上运行多个应用,每个应用分别只用一个类加载器来加载自己的类,那通常也不会掉这坑里——同应用的类都由同类加载器所加载所以在同一命名空间下,没问题;而不同应用之间本来就不应该能相互访问,通过不同类加载器实现隔离,这很好。 但实际情况是类加载器的设计太灵活了,导致类加载器之间依赖关系复杂,然后就可能掉这坑里了… |