字节码技术

前言

阅读对象

本文是博主根据自己经验和查阅资料完成,如有不正确之处欢迎指正。时间宝贵如果你对字节码内幕不敢兴趣,不建议你往下读(不如去研究一下那个英雄更容易上分)。

目标

  1. 了解字节码的意义
  2. 了解字节码如何存储
  3. 了解字节码的内容

字节码结构

技术枯燥,坚持胜利。

背景

学过java我们知道,虚拟机是跨平台技术的一种成熟的解决方案。 而字节码技术是为了同一个虚拟机支持不同语言的解决方案。不严谨的说虚拟机只认识字节码,任何语言只要能编译为字节码都可以在虚拟机上运行(比如:Java、Kotlin、Clojure、Groovy、JRuby、JPython、Scala等语言)。所以字节技术才是跨平台语言诞生的基石,下面用java语言来讲解。

Class文件

一个.class文件表示一个类或者接口,但是一个类或接口不一定要用.class文件类表示(可通过即时编译器生成字节流通过类加载器直接加载使用,java的jdk代理是通过这样的技术来实现)。

文件结构

我们都知道字节码文件是由.class后缀表示的。文件内容是一组8个字节为单位的二进制流,各个数据严格按照顺序紧凑排列在文件之中,中间没有任何空隙和分隔符。根据《java虚拟机规范》这些字节流是用过“无符号数”和“表”两种形式来存储类或者接口的信息。

无符号数

无符号数是属于基本数据类型,以u1、u2、u4、u8来分别代表1个字节、2个字节、4个字节、8个字节。可以用来表示数字、索引引用、数量值和按照UTF-8编码生成的字符串。

表是由无符号数和其他表作为数据项构成的复合数据类型,一般以“_info”结尾。可以说一个字节码文件就是一张大的表。

表结构

class文件是严格按照下表从上到下的顺序紧凑排列。

符号类型名称数量描述
u4magic1魔法数验证文件的合法性
u2minor_version1次版本号
u2major_version1主版本号
u2constant_pool_count1常量池中,常量数量
cp_infoconstant_poolconstant_pool_count-1常量池表
u2access_flags1访问权限标识
u2this_class1类索引
u2super_class1父类索引
u2interfaces_count1接口表中,接口数量
u2interfacesinterfaces_count接口表
u2fields_count1接口或类中申明变量的数量
field_infofieldsfields_count接口或类中申明的变量表
u2methods_count1方法数量
method_infomethodsmethods_count方法表
u2attributes_count1属性
attribute_infoattributesattributes_count属性变量
magic

魔法数,验证class文件的合法性(可以理解为识别码)。

major_version

主版本号,用于标识class文件的版本。java虚拟机只能运行低于自己的版本的class文件。

constant_pool

常量表主要用来存放两大类型常量:字面量和符号引用。

字面量: 文本字符串、被申明为了final的常量值等。
符号引用: 模块导出或开放的包、类或接口的全限定名、字段名称描述符、方法的名称和描述、方法句柄和方法类型、动态调用点和动态常量。

其实常量池中还细分为17种常量类型来存储,具体如下( 借用书上的一张图,读者了解即可)
在这里插入图片描述

access_flags

这是权限访问标识,比如记录一个对象是类还是接口,如果是类是否使用final、abstract、public、private修饰等。

this_class、super_class、interfaces

描述一个类的继承关系和接口实现情况在字节码文件中是通过这三个来描述的。 通过前面我们知道,一个类的基本信息,类名称、方法名称、字段信息等都放在常量池中,所以this_class、super_class和interfaces都是存放着常量池中的索引,表示为当前类全限定名索引、当前类的父类全限定名索引和当前类实现的所有接口的全限定名。

fileds

filed是一张字段表集合,存放描述该类中定义的所有静态变量和实例变量,但不包括方法内定义的局部变量。记录属性访问权限(default、public、private、protected),是实例变量还是静态变量(static),是否是常量(final),是否并发可见性(volatile),是否可被序列化(transient)以及字段的类型和名称。

methods

methods是一长方法表集合,虚拟机设计者们采用了和fields字段表集合几乎一致的方式来描述类中的方法,记录了方法的访问权限标识、是否是静态方法、是否是同步方法,是否是本地方法,名称索引和属性表集合索引(描述方法内部代码的属性表)等。

attributes

属性表是用于存放一些专有属性,比如方法表中代码编译为字节码指令,方法抛出的异常列表,一个匿名类或内部类的文件信息、源码和字节码指令的对应关系等,可以理解为其他项的私有仓库。并且虚拟机中对属性的定义很宽松,只要属性名不重复即可,所以我们可能通过编译器将一些个性化信息保存在其中。

到这里字节码文件内容就完成了。 虚拟机对字节码规范的篇幅很长,本文只是通过博主的理解简单介绍,希望对你有帮助。

总结

字节码技术是相对底层的技术,博主希望读者能通过本博文了解一些字节码的技术内幕。了解我们通常编写的java代码是如何在字节码中存储,给你以后学习java虚拟机类加载机制和内存模型奠定了基础。

参考文献《深入了解Java虚拟机》周志明 第3版
原创不易,转载请标明来源

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

罗德阿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值