前情回顾
上一篇文章中我们详细介绍了常量池,本文我们来介绍Class文件中的访问标志,类索引、父索引和接口索引集合。
访问标志
在常量池结束以后,紧挨着的两个字节代表访问标志(access_flags)。这个标志用来识别一些类和接口层面的访问信息。
我们现在举个实例来说明这个访问标志是如何识别的。
Comments.java
package com.zust.bean;
public class Comments {
private String comments_no;
private String comments_name;
private String comments_context;
private String news_no;
public String getComments_name() {
return comments_name;
}
public void setComments_name(String comments_name) {
this.comments_name = comments_name;
}
public String getComments_context() {
return comments_context;
}
public void setComments_context(String comments_context) {
this.comments_context = comments_context;
}
public String getNews_no() {
return news_no;
}
public void setNews_no(String news_no) {
this.news_no = news_no;
}
public String getComments_no() {
return comments_no;
}
public void setComments_no(String comments_no) {
this.comments_no = comments_no;
}
}
我们可以看到Comments这个类是public ,满足ACC_PUBLIC,版本在JDK1.0.2之后因此也满足ACC_INTERFACE。其余条件接不满足,因此我们得到两个值0x0001和0x0020,在这里我们要将这两个值进行与运算得到0x0021,我们在字节码中对比,验证我们计算的是否正确。
用红圈标出了这两个字节,的确是00 21,所以上述计算是没问题的。
类索引、父索引和接口索引集合
类索引:确定该类的全限定名。
父索引:确定该类的父类的全限定名,由于java父类唯一因此父索引唯一(java.lang.Object不存在父索引)。
接口索引集合:确定该类实现的接口,这些接口按顺序从左到右排列在接口索引集合内。
类索引、父索引都是u2类型的数据,接口索引集合是一组u2类型的数据。它们依次按顺序排列在访问标志后。
类索引、父索引都用u2类型的索引值表示,指向常量池中CONSTANT_Class_info的常量,然后通过该常量找到CONSTANT_Utf8_info的常量。
接口索引集合入口为一u2类型的接口计数器,用来表示接口的数量,如果为0说明该类没有实现接口。
下面列举实例:
Comments.java
package com.zust.bean;
public class Comments {
private String comments_no;
private String comments_name;
private String comments_context;
private String news_no;
public String getComments_name() {
return comments_name;
}
public void setComments_name(String comments_name) {
this.comments_name = comments_name;
}
public String getComments_context() {
return comments_context;
}
public void setComments_context(String comments_context) {
this.comments_context = comments_context;
}
public String getNews_no() {
return news_no;
}
public void setNews_no(String news_no) {
this.news_no = news_no;
}
public String getComments_no() {
return comments_no;
}
public void setComments_no(String comments_no) {
this.comments_no = comments_no;
}
}
我们可以看出该类的全限定名为com/zust/bean/Comments,父类的全限定名为java/lang/Object,没有实现任何接口,下面我们对照它的class文件。
Comments.class
这6个字节依次是类索引、父索引和接口索引集合,类索引是00 01,父索引是00 03,接口索引集合是00 00。下面我们用javap反编译该文件得到常量池。
Last modified 2019-7-4; size 1166 bytes
MD5 checksum f7b9e128edcf563d8216d36602fda343
Compiled from "Comments.java"
public class com.zust.bean.Comments
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Class #2 // com/zust/bean/Comments
#2 = Utf8 com/zust/bean/Comments
#3 = Class #4 // java/lang/Object
#4 = Utf8 java/lang/Object
#5 = Utf8 comments_no
#6 = Utf8 Ljava/lang/String;
#7 = Utf8 comments_name
#8 = Utf8 comments_context
#9 = Utf8 news_no
#10 = Utf8 <init>
#11 = Utf8 ()V
#12 = Utf8 Code
#13 = Methodref #3.#14 // java/lang/Object."<init>":()V
#14 = NameAndType #10:#11 // "<init>":()V
#15 = Utf8 LineNumberTable
#16 = Utf8 LocalVariableTable
#17 = Utf8 this
#18 = Utf8 Lcom/zust/bean/Comments;
#19 = Utf8 getComments_name
#20 = Utf8 ()Ljava/lang/String;
#21 = Fieldref #1.#22 // com/zust/bean/Comments.comments_name:Ljava/lang/String;
#22 = NameAndType #7:#6 // comments_name:Ljava/lang/String;
#23 = Utf8 setComments_name
#24 = Utf8 (Ljava/lang/String;)V
#25 = Utf8 getComments_context
#26 = Fieldref #1.#27 // com/zust/bean/Comments.comments_context:Ljava/lang/String;
#27 = NameAndType #8:#6 // comments_context:Ljava/lang/String;
#28 = Utf8 setComments_context
#29 = Utf8 getNews_no
#30 = Fieldref #1.#31 // com/zust/bean/Comments.news_no:Ljava/lang/String;
#31 = NameAndType #9:#6 // news_no:Ljava/lang/String;
#32 = Utf8 setNews_no
#33 = Utf8 getComments_no
#34 = Fieldref #1.#35 // com/zust/bean/Comments.comments_no:Ljava/lang/String;
#35 = NameAndType #5:#6 // comments_no:Ljava/lang/String;
#36 = Utf8 setComments_no
#37 = Utf8 SourceFile
#38 = Utf8 Comments.java
我们可以看到类索引所指向的CONSTANT_Class_info最终指向的是com/zust/bean/Comments
父索引所指向的CONSTANT_Class_info最终指向的是java/lang/Object,而接口索引集合由于没有接口索引为 00 00。
总结
这篇文章中我们介绍了Class文件中的访问标志、类索引、父索引和接口索引集合。下篇文章中我们将介绍字段表集合和方法表集合。