深入理解java虚拟机-class文件结构(5)

这个就不敲了。。。Class文件格式如下图,class文件就是用下面的的结构组织起来的

u2表示2个字节  u4表示4个字节

常量池的一些类型

 

各常量的结构如下图(不全)

 

写了一个简单的java类

package vm.c2;

public class ClassStructure {

	private int liu ;
	
	public void sumMult(){
		System.out.println(999*100);
	}
	
	public int increment(){
		return liu+1;
	}
}

编译成class文件并且使用十六进制打开 我用的软件是 binary viewer

javap -verbose class文件  用来将字节码 展示给人看懂的结构,实际后面

谈的的解析字节流 最终就是得到这么个类型结构

0000行(16进制,1个长度4位 2个长度代表1个字节)

CA FE BA BE : 类文件结构提到了 有4个字节 即魔数 为CAFE BABE固定的,用来判断是否是class

00 00  00 34 :大版本 小版本 可以通过这个来区分java版本

 00 21 :2个字节的常量池 表示有32(16*2+1)个常量 索引范围是 [1-33)不包括33

第一个常量

0A  00 07  00 13 :表示(根据常量类型)表示方法的符合引用查表得 有一个u1的tag  ,u2的指向class_info索引 , u2类型的nameAndType;tag就是0A,00 07表示指向第7项常量  又指向26项常量即  java/lang/Object 只不过把包名的.改成了/,00 13表示指向第19项常量,19又分别指向常量10和11 即 <init> ()V  表示类的构造方法 并且返回值为空

第二个常量

09 00 14 00 15:查表得Filed_ref_info 有一个u1 tag,一个u2 类型指向class_info索引,一个u2类型的nameAndType

tag就是09 ,00 14表示第20项常量 又指向27 即java/lang/System,0015表示第21项常量 指向常量 28,29。意思是名字叫out对象为Ljava/io/PrintStream(后面会再  类链接阶段进行替换)

第三个常量

03 表示整型字母量 查表的 u1 tag 即03   ,剩下就是bytes java规定 int占四个字节 值为00 01 86 3C

转换为10进制就是99900也就是 编译成class文件的时候 帮我们计算出来了,这个就是java编译的优化,所以别在代码显示

去吧计算好的值填进去,直接写999*100就行了。

后面的常量 基本上都是这个套路就不一一写明了

 

 

常量池结束后就是类访问标志,

调到这个 可以看上面-verbose的输出,定位到最后一个常量完就是

这个值在0130行的00 21

按照上面的访问标志  00 21 表示acc_super和acc_public然后做|运算 可知类是public的

 

然后就是 this_class 

u2类型 00 06 定位到常量池的第6项 即vm/c2/ClassStructure

再就是super_class

u2类型 00 07定位到常量池的第7项 java/lang/Object

再就是 interface_count

u2类型 00 00 表示无接口 就忽略interfaces

再就是fields_count

u2类型 00 01 表示 属性为个数为1

再就是字段fields

类型为field_info 的结构如下

类型名称数量
u2access_flags1
u2name_index1
u2decriptor_index1
u2arrtubutes_count1
attribute_infoattributesattributes_count

 

access_flags   00 02表示 字段为私有的

name_index 00 08 表示 名称 索引为第8项常量 liu

decriptor_index 00 09表示 简单名称 I表示int

简称对应如下(B byte,C char,D double ,F float,I int ,J long , S short , Z boolean ,L 对象类型)

[[Ljava/lang/String 表示 二维字符串数组 , toString() 简称描述符()Ljava/lang/String   ()表示无参数后面是返回值

arrtubutes_count 00 00 没有额外的附加信息

下面就是method_count了

00 03表示有三个方法

方法访问标志

方法表结构

类型名称数量
u2access_flags1
u2name_index1
u2decriptor_index1
u2arrtubutes_count1
attribute_infoattributesattributes_count

 

第一个方法

00 01 访问标志 表示方法是 public

00 0A  第10项常量<init>方法

00 0B 11项常量  ()V表示返回值为空

00 01表示 属性数量为1

 0C 表示第12想常量Code(表示code属性)

下面就是一个4个字节的属性长度  属性长度为整个属性表的长度-6(名称和长度占6个)

00 00 00 1D表示29个长度

00 01表示最大栈长度 1

00 01表示本地变量表的长度

00 00 00 05表示code_length长度为5 表示有5个字节码指令

分别为 0x2A  0x B7  0x 00  0x01  0xB1

这个可以查字节码指令表分别对应起来为

aload_0  第0个Slot加载操作栈,

ivokespecial 表示将栈顶的引用类型为所指向的对象,的构造方法 此指令有一个u2长度的参数为

即<init> 符合引用,

然后就是return

 

其他方法类似  将直接分析javap后的 比如increment方法

操作栈的大小为2, 本地变量表的大小为1 ,参数为1(this是实例方法的第一个slot)不然你代码的this哪来的

引用入操作栈,

获取liu字段的值,并且加载到栈顶

加载常量1到操作栈顶

相加栈顶两个值 并且弹栈,将结果入栈

返回一个int值

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值