Class文件详解(三)

本文深入解析Class文件中的访问标志、类索引、父索引和接口索引集合,揭示Java类加载过程中的关键信息。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前情回顾

上一篇文章中我们详细介绍了常量池,本文我们来介绍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文件中的访问标志、类索引、父索引和接口索引集合。下篇文章中我们将介绍字段表集合和方法表集合。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值