Java .class文件结构 - InnerClasses属性

时间:2014-10-06 11:15:32

标签: java jvm bytecode .class-file

http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.7.6

  

constant_pool表中的每个CONSTANT_Class_info条目   表示不是包成员必须的类或接口C.   在classes数组中只有一个相应的条目。

classes数组是InnerClasses属性的成员。

outer_class_info_index

  

如果C不是类或接口的成员(即C是{{1}}   顶级类或接口(JLS§7.6)或本地类(JLS§14.3)   或者是匿名类(JLS§15.9.5)),值的    outer_class_info_index 项必须为零。

问题:

我认为C甚至可以达到顶级水平(正如之前的报价所说 -

  

“..即,如果C是顶级班级......”

但如果第一个报价单

,C怎么可能是顶级等级
  

“......不是包成员的类或接口C ......”

“not package member”意味着该类必须嵌套对吗?所以它不能成为顶级课程。

2 个答案:

答案 0 :(得分:2)

我认为这是一个很好的语言律师案例。第一个声明说

  

constant_pool表中的每个CONSTANT_Class_info条目   表示不是包成员必须的类或接口C.   在classes数组中只有一个相应的条目。

但是,它没有说顶级类不允许在classes数组中有一个条目。

现在为什么它会在那里进入,我不知道。也许是为了未来的可扩展性。但规范允许它,它将被实现忽略,因为它不是真正的内部/成员类。

因此,这些陈述在技术上并不矛盾。

答案 1 :(得分:0)

与给定类的内部类关系中涉及的每个类都应该在该类的内部类属性中表示。

说,你有A,B和C,B是A的内部类,C是B的内部类。那么它的工作方式是A的内部类属性有A和B的条目, B有A,B和C的条目,C有B和C的条目。至少这是表现良好的代码应该如何工作,但JVM只是部分强制执行它。

现在另一个问题是为什么首先选择这种冗余。

我怀疑其原因是安全方面的好处。最初,内部类属性是完全未选中的,因此您可以创建一个类Foo,并将其声明为任何其他类的内部类,甚至是系统类,如java.lang.Object。但开发人员担心安全性决策可能是基于可欺骗的内部类关系(即Foo是Java包中的内部类,因此必须信任)。他们的解决方案是要求两个类在其内部类属性中相互提及。这样就不可能假装成为一个不了解你的现有阶级的内部阶级。

当然,支票有点破,因为它们只是向一个方向发展。你仍然可以创建一个类Foo并声称java.lang.Object是Foo的内部类。您也可以创建类似Foo的东西,它声称自己是一个内部类。但是当我搜索时,无论如何我都找不到基于内部类的任何实际安全实例,所以这可能是一个没有实际意义的点。