class文件介绍

本文介绍了Java的class文件结构,包括常量池、符号引用和直接引用等关键内容。详细阐述了class文件里的数据布局,如魔数、版本号、访问标志等。还探讨了常量池中的各种类型,如long和double的存储方式、字符串常量的存储限制以及字面量进入常量池的条件。同时,解释了符号引用和直接引用的区别,以及它们在类加载过程中的转换时机。

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

学习记录

class文件介绍

class文件里存了什么数据

xxx-数字 数字表示的字节数

命令:javap -v [class]

魔数-4|副版本号-2|主版本号-2|
常量池计数器-2|常量池数据区-n|
访问标志-2|类索引-2|父类索引-2|
接口计数器-2|接口信息数据区-n|
字段计数器-2|字段信息数据区-n|
方法计数器-2|方法信息数据区-n|
属性计数器-2|属性信息数据区-n|

class常量池

cp_info: 常量池项

constant_pool_count: 常量池计数器

常量池计数器是从 1 开始计数, 而不是从0开始的, 如果constant_pool_count=22
则后面的常量池项(cp_info)的个数是21 (第0项常量空出来单独考虑,为满足某些指向常量池的索引值的数据在待定的情况下表达不引用任何一个常量池项的意思)

cp_info结构

 cp_info {

   u1    tag;

   u1    info[];

 }

tag - 1个字节
info[] - 1个字节组成的数组

tag

1-6属于字面量结构体, 剩余是引用型结构体

字面量结构体:一个cp_info表示,info[]里存储的是字面量值

引用型结构体:两个cp_info表示,一个cp_info表示引用类型,一个cp_info表示utf8_info

Tag值表示的字面量更细化的结构
1字符串常量CONSTANT_Utf8_info
34字节intCONSTANT_Integer_info
44字节floatCONSTANT_Float_info
58字节longCONSTANT_Long_info
68字节doubleCONSTANT_Double_info
7类或接口全限定名CONSTANT_Class_info
8String类型CONSTANT_String_info
9类中的字段CONSTANT_Fieldref_info
10类中的方法CONSTANT_Methodref_info
11类所实现的接口的方法CONSTANT_InterfaceMethodref_info
12字段或方法的名称和类型CONSTANT_NameAndType_info
15方法句柄CONSTANT_MethodHandle_info
16方法类型CONSTANT_MethodType_info
18invokedynamic指令所使用
到的引导方法、引导方法
使用到动态调用名称、参数
和请求返回类型等
CONSTANT_InvokeDynamic_info
示例
  1. tag 为1-6
    cp_info {
      u1 tag=1;
      un info=[xxx];
    }
    
  2. tag 为7-18
    cp_info1 {
     u1 tag=7
     u1 info=[cp_info2索引]
    }
    cp_info2 {
     u1 tag=1;
     un info=[xxx];
    }
    

long和double在常量池中是如何存储的

long_cp_info {
  u1 tag=5;
  u4 high_bytes;
  u4 low_bytes;
}

double_cp_info {
  u1 tag=6;
  u4 high_bytes;
  u4 low_bytes;
}

由此可知long和double虽然是8个字节,但是在计算机中是分成两个4字节进行存储,分为高4位和低4位(为了在32位和64位系统通用)

引出:long和double在操作的时候是否存在线程安全问题

double、float、long不声明final就能在常量池中存在,int不声明final也会存在吗?

解答

String类型的字符串常量在常量池中是怎样存储的?

string_cp_info {
  u1 tag=8;
  u2 constant_pool_index;
}
utf8_cp_info {
  u1 tag=1;
  u2 length;
  u1 bytes[length]
}
那么,字符串常量是否有长度限制呢?

哪些字面量会进入常量池中

  1. final类型的8中基本类型的值
  2. 非final类型(包括static的)的8中基本类型的值,只有double、float、long的值会进入常量池
  3. 常量池中包含的字符串类型字面量(双引号引起来的字符串值)

class中的符号引用和直接引用

符号引用

以一组符号来描述所引用的目标,符号可以使任何形式的字面量。如"/java/Math"

与内存无关

直接引用

  1. 指向目标的指针
  2. 相对偏移量
  3. 一个能间接定位到目标的句柄

引用替换的时机

类加载过程(加载 -> 连接(验证、准备、解析) -> 初始化中的解析阶段

class中的特殊字符串

  1. 类的全限定名
  2. 字段和方法的描述符
  3. 特俗方法的方法名

类的全限定名

在java文件中是java.lang.Object

在class文件中是java/lang/Object

描述符

  1. 类型描述符
  2. 字段描述符
  3. 方法描述符
字段类型描述符
数据类型描述符
byteB
charC
doubleD
floatF
intI
longJ
shortS
booleanZ
特殊类型voidV
对象类型L + 类的全限定名 + ; 如:Ljava/lang/String;
数组类型若干个[ + 数组中元素类型对应的字符串 如 String[][] -> [[Ljava/lang/String;
方法描述符
方法描述符方发声明
()Iint getSize()
()Ljava/lang/String;String toString()
([Ljava/lang/String;)Vvoid main(String[] args)
()Vvoid wait()
(JI)Vvoid wait(long timeout, int nanos)
(ZILjava/lang/String;TT)Zboolean test(boolean a, int b, String c int d, int e)
([BII)Iint test(byte[] b, int a, int c)
()[[Ljava/lang/Object;Object[][] test()
特殊方法的方法名

类的构造方法和类型初始化方法

构造方法

静态初始化方法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值